|
2 | 2 |
|
3 | 3 | ## Classification |
4 | 4 | - **Canonical URI**: `chittycanon://core/services/chittyauth-app` |
5 | | -- **Tier**: 3 (Service Layer) |
| 5 | +- **Tier**: 1 (Core Identity) — function-based; same tier as `chittyauth`, distinguished by deployment model |
6 | 6 | - **Organization**: CHITTYAPPS |
7 | | -- **Domain**: Custom (not auth.chitty.cc) |
| 7 | +- **Domain**: Operator-chosen (no canonical default) |
8 | 8 |
|
9 | 9 | ## Mission |
10 | 10 |
|
11 | | -ChittyAuth App is a **standalone authentication and token provisioning service** designed for independent deployment without ChittyOS infrastructure dependencies. Unlike the OS-integrated `chittyauth` service, this app uses Cloudflare-native storage (D1 + KV) and requires no external database connections. |
| 11 | +ChittyAuth App is a **standalone authentication and token provisioning service** that delivers ChittyAuth-class token issuance without the ChittyOS shared-database backbone. It is a Cloudflare-native build (D1 + KV) intended for third-party deployments, isolated environments, and per-app token authorities. |
12 | 12 |
|
13 | 13 | ## Scope |
14 | 14 |
|
15 | 15 | ### IS Responsible For |
16 | | -- User registration and account management |
17 | | -- API token provisioning with HMAC-SHA256 signatures |
18 | | -- Token validation with KV caching (fast path) |
19 | | -- Token refresh and revocation |
20 | | -- Rate limiting via KV namespaces |
21 | | -- Complete audit logging |
| 16 | +- User registration and account lifecycle (`/v1/register`) |
| 17 | +- API token provisioning, validation, refresh, and revocation |
| 18 | +- HMAC-SHA256 signing + SHA-256 hashed-at-rest token storage |
| 19 | +- KV-first validation cache (30s TTL) and revocation blocklist |
| 20 | +- Per-token rate limiting via KV counters (1h window) |
| 21 | +- Append-only audit logging (D1 `audit_logs`) |
22 | 22 | - OAuth client registration |
23 | | -- D1 SQLite primary storage |
24 | | -- KV-first caching architecture |
25 | 23 |
|
26 | 24 | ### IS NOT Responsible For |
27 | | -- ChittyOS ecosystem integration |
28 | | -- Shared identity tables (uses isolated storage) |
29 | | -- Service-to-service tokens (end-user tokens only) |
30 | | -- ChittyID dependency (can work standalone) |
| 25 | +- Service-to-service tokens (end-user tokens only — use `chittyauth` for inter-service auth) |
| 26 | +- Shared identity tables with `chittyos-core` |
| 27 | +- ChittyID minting (this app authenticates, it does not issue ChittyIDs) |
| 28 | +- Cross-service identity sharing (storage is isolated by design) |
31 | 29 |
|
32 | | -## Comparison to chittyauth |
| 30 | +## Comparison to `chittyauth` |
33 | 31 |
|
34 | | -| Aspect | chittyauth (CHITTYFOUNDATION) | chittyauth-app (CHITTYAPPS) | |
35 | | -|--------|-------------------------------|---------------------------| |
36 | | -| Database | Neon PostgreSQL (chittyos-core) | D1 + KV | |
37 | | -| Dependencies | ChittyID, ChittyConnect required | Optional integrations | |
| 32 | +| Aspect | `chittyauth` (CHITTYFOUNDATION) | `chittyauth-app` (CHITTYAPPS) | |
| 33 | +|--------|---------------------------------|------------------------------| |
| 34 | +| Database | Neon PostgreSQL (chittyos-core) | D1 (SQLite) + KV | |
| 35 | +| Dependencies | ChittyID, ChittyConnect required | Optional (ChittyConnect only) | |
38 | 36 | | Data Sharing | Shares identity data | Isolated storage | |
39 | | -| Deployment | auth.chitty.cc | Any custom domain | |
40 | | -| Use Case | Core ChittyOS services | Third-party apps | |
41 | | -| Token Type | Service + User tokens | End-user tokens only | |
| 37 | +| Domain | `auth.chitty.cc` | Operator-chosen | |
| 38 | +| Token Audience | Service + user | End-user only | |
| 39 | +| Use Case | Core ChittyOS services | Third-party apps, custom deployments | |
42 | 40 |
|
43 | 41 | ## Architecture |
44 | 42 |
|
45 | | -### Storage Backend |
46 | | -**D1 Database** (Primary): |
47 | | -- `api_tokens` - Token records and metadata |
48 | | -- `users` - User accounts |
49 | | -- `audit_logs` - Complete audit trail |
50 | | -- `oauth_clients` - OAuth client registrations |
51 | | - |
52 | | -**KV Namespaces** (Caching): |
53 | | -- `AUTH_TOKENS` - Token validation cache (30s TTL) |
54 | | -- `AUTH_REVOCATIONS` - Revoked token list |
55 | | -- `AUTH_RATE_LIMITS` - Rate limiting counters (1h window) |
56 | | -- `AUTH_AUDIT` - Audit log buffer |
57 | | - |
58 | | -### Token Security |
59 | | -1. Generate token with HMAC-SHA256 signature |
60 | | -2. Hash token with SHA-256 |
61 | | -3. Store only hash in D1 (never plaintext) |
62 | | -4. Return plaintext to user (only time visible) |
| 43 | +### Storage Bindings |
| 44 | +- **D1** (`AUTH_DB`): `users`, `api_tokens`, `audit_logs`, `oauth_clients` |
| 45 | +- **KV**: |
| 46 | + - `AUTH_TOKENS` — validation cache (30s TTL) |
| 47 | + - `AUTH_REVOCATIONS` — revoked-token blocklist |
| 48 | + - `AUTH_RATE_LIMITS` — per-token request counters (1h window) |
| 49 | + - `AUTH_AUDIT` — audit-log buffer |
63 | 50 |
|
64 | 51 | ### Validation Flow |
65 | 52 | ``` |
66 | | -Request → Check KV cache (fast path) |
67 | | - → If miss: Query D1 (slow path) |
68 | | - → Cache valid token for 30 seconds |
69 | | - → Return validation result |
| 53 | +Request → KV cache (fast path) ──hit──→ return |
| 54 | + │ miss |
| 55 | + ▼ |
| 56 | + D1 query → cache (30s) → return |
70 | 57 | ``` |
71 | 58 |
|
72 | | -## API Endpoints |
| 59 | +### Token Format |
| 60 | +JWT-like `header.payload.signature`: |
| 61 | +```json |
| 62 | +{ |
| 63 | + "iss": "chittyauth-app", |
| 64 | + "sub": "<user_id>", |
| 65 | + "aud": ["<application>"], |
| 66 | + "scopes": ["<scope>:<action>"], |
| 67 | + "iat": 0, "exp": 0, |
| 68 | + "jti": "<unique_token_id>" |
| 69 | +} |
| 70 | +``` |
| 71 | +Hashed with SHA-256 before storage; plaintext returned to caller exactly once at issuance. |
| 72 | + |
| 73 | +## API Contract |
73 | 74 |
|
74 | | -### Public (No Auth) |
| 75 | +### Public (no auth) |
75 | 76 | | Endpoint | Method | Purpose | |
76 | 77 | |----------|--------|---------| |
77 | | -| `/v1/register` | POST | Register new user | |
78 | | -| `/health` | GET | Health check | |
| 78 | +| `/v1/register` | POST | Register a user and issue first token | |
| 79 | +| `/health` | GET | Liveness + binding health | |
79 | 80 |
|
80 | | -### Protected (Bearer Token) |
| 81 | +### Protected (Bearer token) |
81 | 82 | | Endpoint | Method | Purpose | |
82 | 83 | |----------|--------|---------| |
83 | | -| `/v1/tokens/provision` | POST | Provision new API token | |
84 | | -| `/v1/tokens/validate` | POST | Validate token | |
85 | | -| `/v1/tokens/refresh` | POST | Refresh token expiration | |
86 | | -| `/v1/tokens/revoke` | POST | Revoke token | |
87 | | -| `/v1/tokens/stats` | GET | Token usage statistics | |
88 | | - |
89 | | -## Token Format |
90 | | - |
91 | | -JWT-like structure: `header.payload.signature` |
92 | | - |
93 | | -```json |
94 | | -{ |
95 | | - "iss": "chittyauth-app", |
96 | | - "sub": "user_id", |
97 | | - "aud": ["myapp"], |
98 | | - "scopes": ["myapp:read", "myapp:write"], |
99 | | - "iat": 1700000000, |
100 | | - "exp": 1700086400, |
101 | | - "jti": "unique_token_id" |
102 | | -} |
103 | | -``` |
| 84 | +| `/v1/tokens/provision` | POST | Issue a new token | |
| 85 | +| `/v1/tokens/validate` | POST | Validate a token | |
| 86 | +| `/v1/tokens/refresh` | POST | Refresh expiration | |
| 87 | +| `/v1/tokens/revoke` | POST | Revoke immediately | |
| 88 | +| `/v1/tokens/stats` | GET | Usage statistics | |
104 | 89 |
|
105 | 90 | ## Dependencies |
106 | 91 |
|
107 | | -| Type | Service | Purpose | |
108 | | -|------|---------|---------| |
109 | | -| Optional | ChittyConnect | External integration | |
110 | | -| Storage | Cloudflare D1 | SQLite database | |
111 | | -| Storage | Cloudflare KV | Caching and rate limiting | |
112 | | -| Runtime | Cloudflare Workers | Serverless edge | |
| 92 | +| Type | Component | Purpose | |
| 93 | +|------|-----------|---------| |
| 94 | +| Runtime | Cloudflare Workers | Edge serverless host | |
| 95 | +| Storage | Cloudflare D1 | Primary persistent store | |
| 96 | +| Storage | Cloudflare KV | Cache, rate limit, revocation, audit buffer | |
| 97 | +| Optional | ChittyConnect | External identity verification (off by default) | |
113 | 98 |
|
114 | 99 | ## Configuration |
115 | 100 |
|
116 | 101 | ### Required Secrets |
117 | | -- `TOKEN_SIGNING_KEY` - 256-bit key for HMAC signatures |
| 102 | +- `CHITTYAUTH_ISSUED_MINT_API_KEY` — canonical 256-bit HMAC key (rotate quarterly) |
118 | 103 |
|
119 | 104 | ### Optional Secrets |
120 | | -- `CHITTYCONNECT_API_KEY` - For ChittyConnect integration |
| 105 | +- `CHITTYAUTH_ISSUED_CONNECT_API_KEY` — canonical connect service token if ChittyConnect integration is enabled |
| 106 | +- `NEON_OAUTH_CLIENT_ID` / `NEON_OAUTH_CLIENT_SECRET` — when `CHITTYAUTH_PROVIDER=neon` |
| 107 | +- Legacy alias support remains for migration: `TOKEN_SIGNING_KEY`, `CHITTYCONNECT_API_KEY` |
121 | 108 |
|
122 | 109 | ### Environment Variables |
123 | | -- `ENVIRONMENT` - "development" or "production" |
124 | | -- `DEFAULT_TOKEN_EXPIRY` - Token lifetime (seconds) |
125 | | -- `MAX_TOKENS_PER_USER` - Token limit per user |
| 110 | +- `ENVIRONMENT` — `development` | `production` |
| 111 | +- `CHITTYAUTH_PROVIDER` — `local` | `neon` |
| 112 | +- `NEON_OAUTH_HOST` — defaults to `https://oauth2.neon.tech` |
| 113 | +- `DEFAULT_TOKEN_EXPIRY` — seconds (default 2592000 = 30d) |
| 114 | +- `MAX_TOKENS_PER_USER` — integer cap |
126 | 115 |
|
127 | 116 | ## Ownership |
128 | 117 |
|
129 | 118 | | Role | Owner | |
130 | 119 | |------|-------| |
131 | 120 | | Service Owner | ChittyApps | |
132 | 121 | | Technical Lead | @chittyapps-team | |
133 | | -| Contact | auth-app@chitty.cc | |
| 122 | +| Security Contact | security@chitty.cc | |
| 123 | +| Service Contact | auth-app@chitty.cc | |
134 | 124 |
|
135 | 125 | ## Compliance |
136 | 126 |
|
137 | | -- [ ] CLAUDE.md development guide present |
138 | | -- [ ] CHARTER.md present |
139 | | -- [ ] CHITTY.md present |
140 | | -- [ ] D1 database initialized with schema |
141 | | -- [ ] All KV namespaces created and bound |
142 | | -- [ ] TOKEN_SIGNING_KEY secret set (256-bit) |
143 | | -- [ ] Health endpoint operational |
144 | | -- [ ] Registration endpoint tested |
145 | | -- [ ] Rate limiting verified |
146 | | - |
147 | | -## Security Checklist |
148 | | - |
149 | | -- [ ] Rotate TOKEN_SIGNING_KEY quarterly |
150 | | -- [ ] Monitor audit logs for suspicious activity |
151 | | -- [ ] Token expiration set (30 days max) |
152 | | -- [ ] Rate limiting on all endpoints |
153 | | -- [ ] HTTPS only in production |
154 | | -- [ ] Never log token values (only hashes) |
| 127 | +Operational gate (must be green before deploy): |
| 128 | +- [ ] D1 database created and `schema.sql` applied |
| 129 | +- [ ] All four KV namespaces created and bound in `wrangler.toml` |
| 130 | +- [ ] `CHITTYAUTH_ISSUED_MINT_API_KEY` set via `wrangler secret put` |
| 131 | +- [ ] If Neon-backed mode is enabled: `CHITTYAUTH_PROVIDER=neon` and Neon OAuth secrets are present |
| 132 | +- [ ] `/health` returns `{"status":"healthy"}` with `checks.database` and `checks.kv` true |
| 133 | +- [ ] `/v1/register` smoke test succeeds end-to-end |
| 134 | +- [ ] `/v1/tokens/validate` confirms KV-cache hit on second call |
| 135 | +- [ ] CHARTER.md, CHITTY.md, CLAUDE.md, AGENTS.md, SECURITY.md present and consistent |
| 136 | + |
| 137 | +Documentation gate: |
| 138 | +- [ ] No mocked/placeholder routes in committed code (per global no-mocks policy) |
| 139 | +- [ ] No fake or seeded data in `schema.sql` (real shapes only) |
155 | 140 |
|
156 | 141 | --- |
157 | | -*Charter Version: 1.1.0 | Last Updated: 2026-02-21* |
| 142 | +*Charter Version: 1.2.0 | Last Updated: 2026-05-02* |
0 commit comments