# J1 — Architecture: Digital Key Management | Field | Value | |-------|-------| | **J-Flow Phase** | J1 — Logical Design | | **Service ID** | 001 | | **Source** | J0-functional-requirements.md; DKM pp. 3–8 | | **Constitution** | 8 principles | --- ## 1. Module Decomposition ``` KeyManagementService ├── KeyShareController — REST API surface, auth enforcement │ ├── POST /keys/share — Share a key with a recipient │ ├── POST /keys/revoke — Revoke an active shared key │ ├── GET /keys/{vin}/list — List all keys for a vehicle │ └── GET /keys/{key_id}/status — Query key state ├── KeyService — Business logic layer │ ├── KeyShareValidator — Permission, validity, duplicate checks │ ├── KeyStateMachine — Lifecycle transitions │ ├── KeyAuditLogger — Append-only audit trail │ └── KeyConfigGenerator — Builds configuration payload for vehicle ├── KeyRepository — Data access layer │ ├── KeyStore (PostgreSQL) — DigitalKey entities, CRUD │ └── AuditStore (PostgreSQL) — KeyAuditLog append-only writes ├── KeyTrackingClient — Client to Key Tracking Server │ └── GET/PUT key tracking info for device-switch continuity ├── TelematicsGatewayClient — Client to Telematics Gateway │ └── Push key config/revocation to vehicle └── NotificationClient — Client to Honda Connected Services └── Push notification to recipient smartphone ``` ### Shared Infrastructure (external, not part of this service) | Component | Purpose | |-----------|---------| | **Telematics Gateway** | Relays key configuration and revocation commands to the vehicle | | **Push Notification Service** | Delivers key-share notifications to recipient smartphones | | **Honda Connected Services** | Manages user identity, OAuth tokens, device registration | | **Key Tracking Server** | Retains digital key metadata across device switches | --- ## 2. API Contracts ### 2.1 POST /keys/share Share a digital key with a recipient. ``` POST /keys/share Authorization: Bearer Content-Type: application/json Request: { "vehicle_vin": string, // 17-char VIN, SHALL be owned by authenticated user "recipient_user_id": string, // UUID of recipient (PII — tagged) "recipient_email": string, // Email for notification (PII — tagged) "validity_start": ISO8601, // Start of validity window "validity_end": ISO8601, // End of validity window; SHALL be ≤ 90 days from now "restrictions": { "max_speed_kmh": int|null, // Optional speed cap "geo_fence": string|null, // Optional geofence polygon "time_window_start": string|null, // Optional daily time restriction "time_window_end": string|null } } Response 201: { "key_id": string, // UUID of created friend key "owner_key_id": string, // UUID of owner's key "status": "Shared", "validity_start": ISO8601, "validity_end": ISO8601, "restrictions": { ... }, "created_at": ISO8601 } Error Codes: 400 INVALID_PERMISSION — User does not own the specified VIN 400 INVALID_VALIDITY — validity_end > now + 90 days or end ≤ start 409 DUPLICATE_SHARE — Active share already exists for this owner+vin+recipient 404 VIN_NOT_FOUND — Vehicle not registered to this owner 401 UNAUTHORIZED — Invalid or expired token ``` ### 2.2 POST /keys/revoke Revoke an active shared key. ``` POST /keys/revoke Authorization: Bearer Content-Type: application/json Request: { "key_id": string, // UUID of the friend key to revoke "reason": string // Free-text reason (optional, logged to audit) } Response 200: { "key_id": string, "status": "Revoked", "revoked_at": ISO8601, "revoked_by": string // owner user_id } Error Codes: 404 KEY_NOT_FOUND — key_id does not exist 403 NOT_KEY_OWNER — authenticated user is not the key owner 409 ALREADY_REVOKED — key is already in Revoked state ``` ### 2.3 GET /keys/{vin}/list List all keys for a vehicle. ``` GET /keys/{vin}/list?status=active&limit=50&offset=0 Authorization: Bearer Response 200: { "vin": string, "keys": [ { "key_id": string, "key_type": "owner" | "friend", "status": "Active" | "Expiring" | "Expired" | "Revoked" | "Shared", "recipient_user_id": string | null, "validity_start": ISO8601, "validity_end": ISO8601, "restrictions": { ... }, "created_at": ISO8601 } ], "total": int, "limit": int, "offset": int } Error Codes: 404 VIN_NOT_FOUND — Vehicle not registered 403 NOT_VIN_OWNER — Authenticated user does not own this VIN ``` ### 2.4 GET /keys/{key_id}/status Query the current state of a specific key. ``` GET /keys/{key_id}/status Authorization: Bearer Response 200: { "key_id": string, "key_type": "owner" | "friend", "status": "Active" | "Expiring" | "Expired" | "Revoked" | "Shared", "vehicle_vin": string, "owner_user_id": string, "recipient_user_id": string | null, "validity_start": ISO8601, "validity_end": ISO8601, "restrictions": { ... }, "last_used_at": ISO8601 | null, "created_at": ISO8601, "updated_at": ISO8601 } Error Codes: 404 KEY_NOT_FOUND — key_id does not exist 403 NOT_KEY_OWNER — authenticated user is not the key owner ``` --- ## 3. Key Lifecycle State Machine ``` ┌──────────────────────────────────────────────┐ │ │ ▼ │ ┌─────────┐ share() ┌────────┐ recipient ┌────────┐ │ │ Created │──────────▶│ Shared │─────────────▶│ Active │ │ └─────────┘ └────────┘ accepts key └────────┘ │ │ │ │ revoke() │ nearing │ revoke() from any state │ expiry │ │ ▼ ▼ │ ┌──────────┐ ┌────────┐ │ │ Revoked │ │Expiring│ │ └──────────┘ └────────┘ │ │ │ expiry│ │ reached│ │ ▼ │ ┌────────┐ │ │Expired │──┘ └────────┘ revoke() ``` ### Transitions | From | To | Trigger | Guard | |------|----|---------|-------| | — | Created | Owner registers vehicle | Vehicle VIN validated | | Created | Shared | Owner calls POST /keys/share | Owner owns VIN; validity window valid | | Shared | Active | Recipient accepts key in app | Key not expired; key not revoked | | Active | Expiring | System cron: validity_end ≤ 7 days away | Key status = Active | | Expiring | Expired | System cron: validity_end ≤ now | Key status = Expiring | | Active | Revoked | Owner calls POST /keys/revoke | Owner owns key | | Expiring | Revoked | Owner calls POST /keys/revoke | Owner owns key | | Shared | Revoked | Owner calls POST /keys/revoke | Owner owns key | | Expired | Revoked | Owner calls POST /keys/revoke | Owner owns key (administrative) | --- ## 4. Architecture Decision Record (ADR) ### ADR-001: Server-Authoritative Key Decisions **Status**: Accepted **Date**: 2026-06-23 **Context**: The vehicle is intermittently connected. If key validity decisions were made on the vehicle, an attacker could tamper with the vehicle to extend key access offline. **Decision**: The Key Management Server is the sole authority for key state. The vehicle caches the latest configuration but always defers to the server when connectivity is available. Offline operation is bounded to the last-known-good configuration for a maximum of 24 hours. **Consequences**: - Vehicle must have a "last-known-good" cache with TTL - Push notification infrastructure must be highly reliable for revocations - Adds latency for vehicle-side key validation if connectivity is poor - Aligns with Constitution principle 4 (Server-Authoritative) ### ADR-002: Split Key Tracking from Key Management **Status**: Accepted **Date**: 2026-06-23 **Context**: Key tracking (persisting digital key metadata across device switches) has different availability and data patterns than active key management (share, revoke, validate). **Decision**: Key Tracking Server operates as a separate service, called asynchronously by Key Management Service. Key Mgmt owns the operational state machine; Key Tracking owns the long-lived metadata archive. **Consequences**: - Two services to maintain and deploy - Key Mgmt can operate if Key Tracking is temporarily unavailable (eventual consistency) - Clearer separation of concerns for audit and compliance --- ## 5. Review Checklist - [ ] All 4 API contracts have request/response shapes and error codes - [ ] Key lifecycle state machine enumerates all transitions - [ ] ADR-001 establishes server-authoritative posture - [ ] ADR-002 separates Key Tracking from Key Management - [ ] Shared infrastructure dependencies identified (Telematics Gateway, Push Notification, Honda Connect) - [ ] No version-change language, no "deferred" notes - [ ] Stakeholder sign-off: ________________ Date: ________________