Subscriber Data Lifecycle
Relevant source files
The following files were used as context for generating this wiki page: - [newsletter-program/src/core/subscriber-file-manager.js](https://github.com/thomas-iniguez-visioli/portfolio/blob/HEAD/newsletter-program/src/core/subscriber-file-manager.js) - [themes/matrix-flow/source/js/newsletter.js](https://github.com/thomas-iniguez-visioli/portfolio/blob/HEAD/themes/matrix-flow/source/js/newsletter.js) - [newsletter-program/README-SUBSCRIBER-MANAGEMENT.md](https://github.com/thomas-iniguez-visioli/portfolio/blob/HEAD/newsletter-program/README-SUBSCRIBER-MANAGEMENT.md) - [newsletter-program/src/cli/subscriber-cli.js](https://github.com/thomas-iniguez-visioli/portfolio/blob/HEAD/newsletter-program/src/cli/subscriber-cli.js) - [newsletter-program/src/core/analytics-manager.js](https://github.com/thomas-iniguez-visioli/portfolio/blob/HEAD/newsletter-program/src/core/analytics-manager.js) - [newsletter-program/src/core/secure-export.js](https://github.com/thomas-iniguez-visioli/portfolio/blob/HEAD/newsletter-program/src/core/secure-export.js) - [newsletter-program/src/tests/integration/newsletter-subscription-flow.test.js](https://github.com/thomas-iniguez-visioli/portfolio/blob/HEAD/newsletter-program/src/tests/integration/newsletter-subscription-flow.test.js)The subscriber management system is a file-based, privacy-focused architecture for handling newsletter subscribers. It manages the entire lifecycle of subscriber data, from initial capture on the frontend to secure, encrypted storage and eventual removal or export for GDPR compliance. The system avoids external database dependencies, relying on an encrypted JSON file (subscribers.encrypted.json) as its single source of truth.
Data operations are primarily handled through a comprehensive set of CLI tools and automated GitHub Actions. All personally identifiable information, specifically email addresses, is encrypted at rest using AES-256-CBC to ensure data privacy. The lifecycle also includes analytics event tracking for actions like subscriptions and unsubscriptions, providing insights into subscriber behavior without compromising security.
Sources: newsletter-program/README-SUBSCRIBER-MANAGEMENT.md, newsletter-program/src/core/subscriber-file-manager.js
System Architecture
The system is composed of several key components that interact to manage subscriber data. The frontend captures the initial request, which is then processed by backend automation, stored securely, and managed via CLI tools.
The following diagram illustrates the high-level architecture of the subscriber management system.
Stage 1: Subscription and Data Ingress
The lifecycle begins when a user subscribes through the newsletter form on the website. This process is designed to be secure, using GitHub Issues as a transport mechanism to avoid exposing credentials on the client-side.
Frontend Subscription Flow
- Data Capture: The user fills out the form with their email, preferred frequency, and topics of interest.
- Client-Side Validation: The
NewsletterManagerclass innewsletter.jsperforms real-time and on-blur validation for the email address, including format checks, suggestions for common domain typos, and rejection of disposable email addresses. It also validates that consent has been given. - GitHub Issue Creation: Upon submission, the frontend does not send data to a traditional API endpoint. Instead, it constructs a URL that opens a new GitHub issue in the designated repository, pre-filled with the subscriber's details in a structured format. This is the primary method for data ingress.
Sources: themes/matrix-flow/source/js/newsletter.js:10-17, 120-210, 417-430
The sequence diagram below shows the subscription flow from the user's interaction to the creation of the GitHub issue.
Backend Processing
Although the specific GitHub Action workflow is not present in the provided files, its behavior is described in integration tests and READMEs.
- Issue Trigger: A GitHub Action is triggered when a new issue with the
newsletter-subscriptionlabel is created. - Data Extraction: The action parses the issue body to extract the subscriber's email and preferences.
- Add Subscriber: It then calls the
SubscriberFileManagerto add the new subscriber to thesubscribers.encrypted.jsonfile. - Welcome Email: A welcome email is sent to the subscriber.
- Issue Cleanup: The issue is commented on, labeled as processed, and closed. For privacy, it is scheduled for deletion after a set period.
Sources: newsletter-program/src/tests/integration/newsletter-subscription-flow.test.js:100-140, themes/matrix-flow/README-newsletter.md
Stage 2: Data Storage and Structure
All subscriber data is managed by the SubscriberFileManager class and stored in a single encrypted JSON file.
Sources: newsletter-program/src/core/subscriber-file-manager.js
Subscriber Data Model
Each subscriber is represented by a JavaScript object with the following structure.
| Field | Type | Description |
|---|---|---|
id | string (UUID) | A unique identifier for the subscriber. |
email | string | The subscriber's email address (decrypted in memory, encrypted at rest). |
status | string | active, unsubscribed, or bounced. |
subscribedAt | string (ISO 8601) | The timestamp when the subscription was created. |
unsubscribedAt | string (ISO 8601) | Optional timestamp for when the user unsubscribed. |
source | string | The origin of the subscription (e.g., website, import, cli). |
preferences | object | Contains frequency (weekly/monthly) and an array of topics. |
unsubscribeToken | string | A cryptographically secure token for one-click unsubscription. |
metadata | object | Optional data like ipAddress, userAgent, and referrer. |
Sources: newsletter-program/README-SUBSCRIBER-MANAGEMENT.md, newsletter-program/src/core/subscriber-file-manager.js:137-154
Encrypted File Structure
The subscribers.encrypted.json file stores subscriber data securely. The SubscriberFileManager handles the encryption and decryption of email addresses transparently when loading or saving the file.
The structure of the stored file is as follows:
{
"version": "1.0.0",
"createdAt": "2025-10-31T10:00:00Z",
"lastModified": "2025-10-31T15:30:00Z",
"keyVersion": "env-v1",
"subscribers": [
{
"id": "uuid",
"encryptedEmail": "encrypted-hex-string:iv-hex-string",
"status": "active",
"subscribedAt": "2025-10-31T10:00:00Z",
"source": "website",
"preferences": {
"frequency": "weekly",
"topics": ["development"]
},
"unsubscribeToken": "secure-token"
}
]
}
Note: The encryptedEmail format is a simplified representation. The actual implementation uses an object with iv and encrypted fields in some documentation, but the code in subscriber-file-manager.js appears to handle a single string.
Sources: newsletter-program/README-SUBSCRIBER-MANAGEMENT.md, newsletter-program/src/core/subscriber-file-manager.js:103-106
Backups
Before any modification, the saveSubscribers function automatically creates a timestamped backup of the subscribers.encrypted.json file in the backups/ directory. The system retains the last 10 backups and prunes older ones.
Sources: newsletter-program/src/core/subscriber-file-manager.js:96-99, 532-554
Stage 3: Management via CLI
The subscriber-cli.js provides a command-line interface for developers to manage the subscriber list directly. This tool interacts with the SubscriberFileManager to perform CRUD operations.
| Command | Description |
|---|---|
add | Adds a new subscriber. |
list | Lists subscribers with filtering options. |
update | Updates an existing subscriber's status or preferences. |
remove | Permanently removes a subscriber by ID. |
stats | Shows statistics like total, active, and unsubscribed counts. |
export | Exports subscriber data to JSON, CSV, or TXT formats. |
import | Imports subscribers from a JSON, CSV, or TXT file. |
validate | Checks the integrity of the subscriber file. |
optimize | Removes duplicate entries from the subscriber file. |
Sources: newsletter-program/src/cli/subscriber-cli.js
Stage 4: Analytics and Event Tracking
The AnalyticsManager class is responsible for tracking key events in the subscriber lifecycle. These events are stored in analytics.json.
- Event Recording: The
recordSubscriberEventfunction is called to log events such assubscribe,unsubscribe,bounce, orupdate. - Reporting: The manager can generate reports on subscriber growth, engagement, and churn rates based on this event data.
Sources: newsletter-program/src/core/analytics-manager.js:77-98, 103-151
Stage 5: Unsubscription and Data Removal
The final stage of the lifecycle involves a subscriber choosing to unsubscribe or a developer removing their data.
Unsubscription Flow
The unsubscription process is designed to be simple and secure.
This diagram illustrates the token-based unsubscription process.
Sources: newsletter-program/src/core/subscriber-file-manager.js:255-270
Data Removal and GDPR
The system provides GDPR-compliant mechanisms for data handling.
- Permanent Deletion: The
removeSubscriberfunction, accessible via thesubscriber-cli removecommand, permanently deletes a subscriber's record from the JSON file. - Data Portability: The
SecureExportManagerclass includes acreateGDPRExport(email)function. This generates a complete JSON export of a specific subscriber's data, including their profile information and all associated analytics events, fulfilling the "right to data portability".
Sources: newsletter-program/src/core/subscriber-file-manager.js:231-246, newsletter-program/src/core/secure-export.js:93-141
Conclusion
The Subscriber Data Lifecycle is a robust, self-contained system that prioritizes security and privacy. By leveraging a file-based architecture with strong encryption and a unique GitHub Issue-based ingress mechanism, it provides a full suite of tools for managing newsletter subscribers. The lifecycle is well-defined, from a secure and validated subscription process to clear paths for unsubscription and GDPR-compliant data removal, all manageable through a powerful command-line interface.