Compare commits

..

No commits in common. "60a6825dfd9fd257d68fb48a9f068bf2c07185f3" and "cd58b1c1cd389516d15128f6b6fd886bd5ec65ee" have entirely different histories.

5 changed files with 50 additions and 204 deletions

View File

@ -4,7 +4,6 @@ title: Set up Cloudflare D1 email-collector database for cross-site subscription
status: To Do
assignee: []
created_date: '2025-12-04 12:00'
updated_date: '2025-12-04 12:03'
labels:
- infrastructure
- cloudflare
@ -52,95 +51,3 @@ Create a standalone Cloudflare D1 database for collecting email subscriptions ac
- [ ] #7 Rate limiting prevents spam submissions
- [ ] #8 At least one site integrated and collecting emails
<!-- AC:END -->
## Implementation Plan
<!-- SECTION:PLAN:BEGIN -->
## Implementation Steps
### 1. Create D1 Database
```bash
wrangler d1 create email-collector
```
### 2. Create Schema File
Create `worker/email-collector-schema.sql`:
```sql
-- Email Collector Schema
-- Cross-site email subscription management
CREATE TABLE IF NOT EXISTS subscribers (
id TEXT PRIMARY KEY,
email TEXT NOT NULL,
email_hash TEXT NOT NULL, -- For duplicate checking
source_site TEXT NOT NULL,
source_page TEXT,
referrer TEXT,
ip_country TEXT,
subscribed_at TEXT DEFAULT (datetime('now')),
verified INTEGER DEFAULT 0,
verified_at TEXT,
unsubscribed INTEGER DEFAULT 0,
unsubscribed_at TEXT,
metadata TEXT -- JSON for custom fields
);
CREATE TABLE IF NOT EXISTS verification_tokens (
id TEXT PRIMARY KEY,
email TEXT NOT NULL,
token TEXT UNIQUE NOT NULL,
expires_at TEXT NOT NULL,
used INTEGER DEFAULT 0,
created_at TEXT DEFAULT (datetime('now'))
);
-- Rate limiting table
CREATE TABLE IF NOT EXISTS rate_limits (
ip_hash TEXT PRIMARY KEY,
request_count INTEGER DEFAULT 1,
window_start TEXT DEFAULT (datetime('now'))
);
-- Indexes
CREATE INDEX IF NOT EXISTS idx_subs_email_hash ON subscribers(email_hash);
CREATE INDEX IF NOT EXISTS idx_subs_site ON subscribers(source_site);
CREATE INDEX IF NOT EXISTS idx_subs_page ON subscribers(source_site, source_page);
CREATE INDEX IF NOT EXISTS idx_subs_verified ON subscribers(verified);
CREATE UNIQUE INDEX IF NOT EXISTS idx_subs_unique ON subscribers(email_hash, source_site);
CREATE INDEX IF NOT EXISTS idx_tokens_token ON verification_tokens(token);
```
### 3. Create Worker Endpoints
Create `worker/emailCollector.ts`:
```typescript
// POST /api/subscribe
// GET /api/verify/:token
// POST /api/unsubscribe
// GET /api/emails/export (auth required)
// GET /api/emails/stats
```
### 4. Export Formats
- CSV: `email,source_site,source_page,subscribed_at,verified`
- JSON: Full object array
- Mailchimp: CSV with required headers
### 5. Admin Authentication
- Use simple API key for export endpoint
- Store in Worker secret: `EMAIL_ADMIN_KEY`
### 6. Integration
Add to each site's signup form:
```javascript
fetch('https://canvas.jeffemmett.com/api/subscribe', {
method: 'POST',
body: JSON.stringify({
email: 'user@example.com',
source_site: 'mycofi.earth',
source_page: '/newsletter'
})
})
```
<!-- SECTION:PLAN:END -->

View File

@ -1,17 +1,17 @@
---
id: task-019
title: Configure CryptID secrets and SendGrid integration
id: task-016
title: Configure CryptID secrets and environment variables
status: To Do
assignee: []
created_date: '2025-12-04 12:02'
created_date: '2025-12-04 12:00'
labels:
- infrastructure
- cloudflare
- cryptid
- secrets
- sendgrid
- email
dependencies:
- task-018
- task-015
priority: high
---

View File

@ -0,0 +1,43 @@
---
id: task-016
title: Create Cloudflare D1 cryptid-auth database
status: To Do
assignee: []
created_date: '2025-12-04 12:00'
labels:
- infrastructure
- cloudflare
- d1
- cryptid
- auth
- security
dependencies: []
priority: high
---
## Description
<!-- SECTION:DESCRIPTION:BEGIN -->
Create the D1 database on Cloudflare for CryptID authentication system. This is the first step before deploying the email recovery feature.
**Database Purpose:**
- Store user accounts linked to CryptID usernames
- Store device public keys for multi-device auth
- Store verification tokens for email/device linking
- Enable account recovery via verified email
**Security Considerations:**
- Emails should be encrypted at rest (Phase 2)
- Public keys are safe to store (not secrets)
- Tokens are time-limited and single-use
- No passwords stored (WebCrypto key-based auth)
<!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria
<!-- AC:BEGIN -->
- [ ] #1 D1 database 'cryptid-auth' created via wrangler d1 create
- [ ] #2 D1 database 'cryptid-auth-dev' created for dev environment
- [ ] #3 Database IDs added to wrangler.toml (replacing placeholders)
- [ ] #4 Schema from worker/schema.sql deployed to both databases
- [ ] #5 Verified tables exist: users, device_keys, verification_tokens
<!-- AC:END -->

View File

@ -4,7 +4,6 @@ title: Deploy CryptID email recovery to dev branch and test
status: To Do
assignee: []
created_date: '2025-12-04 12:00'
updated_date: '2025-12-04 12:02'
labels:
- feature
- cryptid
@ -12,8 +11,8 @@ labels:
- testing
- dev-branch
dependencies:
- task-018
- task-019
- task-015
- task-016
priority: high
---

View File

@ -1,103 +0,0 @@
---
id: task-018
title: Create Cloudflare D1 cryptid-auth database
status: To Do
assignee: []
created_date: '2025-12-04 12:02'
updated_date: '2025-12-04 12:02'
labels:
- infrastructure
- cloudflare
- d1
- cryptid
- auth
dependencies: []
priority: high
---
## Description
<!-- SECTION:DESCRIPTION:BEGIN -->
Create the D1 database on Cloudflare for CryptID authentication system. This is the first step before deploying the email recovery feature.
**Database Purpose:**
- Store user accounts linked to CryptID usernames
- Store device public keys for multi-device auth
- Store verification tokens for email/device linking
- Enable account recovery via verified email
**Security Considerations:**
- Emails should be encrypted at rest (task-016)
- Public keys are safe to store (not secrets)
- Tokens are time-limited and single-use
- No passwords stored (WebCrypto key-based auth)
<!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria
<!-- AC:BEGIN -->
- [ ] #1 D1 database 'cryptid-auth' created via wrangler d1 create
- [ ] #2 D1 database 'cryptid-auth-dev' created for dev environment
- [ ] #3 Database IDs added to wrangler.toml (replacing placeholders)
- [ ] #4 Schema from worker/schema.sql deployed to both databases
- [ ] #5 Verified tables exist: users, device_keys, verification_tokens
<!-- AC:END -->
## Implementation Plan
<!-- SECTION:PLAN:BEGIN -->
## Implementation Steps
### 1. Create D1 Databases
Run from local machine or Netcup (requires wrangler CLI):
```bash
cd /home/jeffe/Github/canvas-website
# Create production database
wrangler d1 create cryptid-auth
# Create dev database
wrangler d1 create cryptid-auth-dev
```
### 2. Update wrangler.toml
Replace placeholder IDs with actual database IDs from step 1:
```toml
[[d1_databases]]
binding = "CRYPTID_DB"
database_name = "cryptid-auth"
database_id = "<PROD_ID_FROM_STEP_1>"
[[env.dev.d1_databases]]
binding = "CRYPTID_DB"
database_name = "cryptid-auth-dev"
database_id = "<DEV_ID_FROM_STEP_1>"
```
### 3. Deploy Schema
```bash
# Deploy to dev first
wrangler d1 execute cryptid-auth-dev --file=./worker/schema.sql
# Then production
wrangler d1 execute cryptid-auth --file=./worker/schema.sql
```
### 4. Verify Tables
```bash
# Check dev
wrangler d1 execute cryptid-auth-dev --command="SELECT name FROM sqlite_master WHERE type='table';"
# Expected output:
# - users
# - device_keys
# - verification_tokens
```
### 5. Commit wrangler.toml Changes
```bash
git add wrangler.toml
git commit -m "chore: add D1 database IDs for cryptid-auth"
```
<!-- SECTION:PLAN:END -->