Skip to content

Revision History

Version Date Changes
8.0 June 2026 Full reorganization for a feature-builder — 21-section layout grouped into six Parts (Orientation / Platform Foundations / Capabilities / Interfaces & Reference / Build & Operate / Appendix). No capability content was dropped; the only intentional removal is the KYC integration detail (below).

New consolidated sections:
§5 Data Model — single canonical home for every entity schema (users, tenant, console_users, oauth_clients, refresh_tokens, webhook_endpoints, devices, challenges, device_transactions, linked_services, consent_records, audit_log, kyc_data hooks, platform_secrets) plus the data-separation diagram and palm namespace/model notes. Absorbs the old §5 User Model and §16 Data Architecture. Entities the prior spec never schematized (e.g. refresh_tokens fields) are flagged ⚠ Open Question rather than invented.
§10 Linked Services & Device Transactions (Broker) — merges the old §4.9 registry and the old §11.8 broker into one feature section.
§15 Error Reference — merges platform HTTP errors (old §13.4), palm-vendor codes (old §19.7), Nafath status (old §19.8), and previously-inline codes (tenant_suspended, consent_required, palm_type_restricted).
§16 Event Reference — unifies the audit catalog (old §10.3.2) and the webhook catalog (old §11.5) into one table mapping each business event to its audit + webhook names.

Moves: old §11 Outbound Integrations split into §10 (broker) and §12 Webhooks; webhook signing-secret lifecycle relocated from old §6.5 to §12.3; user lifecycle moved to §13.5; product context folded from the old appendix into §1 (capabilities → §1.5, out-of-scope → §1.4); palm/Nafath error codes moved out of the appendix into §15. Added a terminology-disambiguation note to §2.

KYC reduced to a [POST-MVP] stub (§7). Removed the un-architected detail (port interface, session/result schemas, provider config, KYC APIs, Nafath flow, the §20 KYCProvider/Nafath code examples, and the detailed KYC Data Schema). Retained all live hooks: kyc_* settings (§4.5), kyc_status/kyc_data (§5.5), enrollment gating (§13.2), KYC audit/webhook events (§16), and the /v1/kyc/* endpoints (§14.1, tagged [POST-MVP]).

Cross-references: every live in-document § reference was remapped to the new numbering and the Table of Contents + anchors regenerated. The revision-history entries below are unchanged — their section numbers are point-in-time records of the layout at each version. Companion diagram cross-references to PRD sections were updated separately; the diagrams file was not reordered, and the KYC sequence (diagrams §3) is left for a follow-up.

Post-restructure reconciliation: added id to linked_services (§5.4); generalized device_certs_bulk_revoked to also cover tenant-scoped forced rotation (§16 / §9.2); cataloged review_case with a ⚠ schema flag (§5); made §8.13 the canonical palm-model definition; tagged KYC [POST-MVP] in §1.2 / §1.3. Subsequent passes improved readability of the densest sections (§8.13, §9.2.1, §9.2.2, §4.6, §4.7, §5.2, §8.3) and moved inline version-history into this changelog — removed the §9.1 "Changed in v7.0" callout, de-tagged §4.7 and the companion diagrams' "New in vX" notes; the body now reads present-tense.
7.2 June 2026 Palm model (small vs large) + small→large migration. Documented that X-Telcom BioWave ships as two deployment-wide palm models and the existing /KZ/* flows are the large model only.

§8.13 Palm Model (Small vs Large): small model = device client SDK matches at the verification server directly and the platform records a device-trusted boolean (user_id + pass/fail), platform outside the matching path; large model = server-to-server /KZ/* with palm_match_policy. Added a feature-applicability table (marks §8.4 score model, §8.10 duplicate detection, §8.11 restrictions, §8.12.2 thresholds large-model-only) and made the platform-side behavioral switch explicit — the active model selects how every device-facing palm endpoint (/v1/device/transactions, /v1/device/enroll, challenge /v1/verify + /v1/enroll + /complete) is handled (results vs scans).

§8.14 Small→Large Migration: platform-orchestrated, one-way; a configured verification-server endpoint lets the platform run the vendor-supplied migration script against the verification server (reprocesses stored RGB+IR — no re-enrollment), then atomically switches the deployment's model.

§13.2: added GET /v1/admin/palm/model, GET/PUT /v1/admin/palm/verification-server, POST /v1/admin/palm/migrate. §13.1: noted device-facing palm endpoints differ by model. §11.8: small-model broker branch (device brings matched user_id; platform skips its own identify). §10.3.2: added palm_model_changed, palm_model_migration_started/completed/failed; qualified identification / verification_complete with source. §16/§17: deployment = platform + paired verification server; model + verification-server endpoint stored deployment-level. Qualified §8.4 / §8.9 blanket statements with "large model".

Companion diagrams bumped to v2.9: added §4.5 (small-model device transaction — SDK-direct match, platform records + authorizes) and §9.3 (small→large migration); disambiguated §4.3 / §4.4 as large-model paths; fixed §9.2 threshold-diagram drift (10→4, pre-existing from the v7.0 10→4 score-model change).
7.1 June 2026 Removed automatic OAuth client creation at tenant provisioning. §4.4: dropped the step that auto-minted the first OAuth client (client_id + client_secret); renumbered. §13.2: POST /v1/admin/tenants no longer returns a "first OAuth client" (only tenant_id + first Tenant Admin credentials). Clients continue to be created via the existing POST /v1/clients endpoint (§6.4; §13.1) — API or Web Console.
7.0 June 2026 Device-initiated palm flows + Linked-Service Broker — major: reverses device ownership and removes the public /v1/identify endpoint.

Device ownership reversed (§9): POS/gate/kiosk devices are now Identity-managed (same pairing/mTLS/revocation lifecycle as personal scanners), not vertical-managed. Added device_class and §9.3 Device → Product Binding (bound_product/bound_action). Rewrote §9.1; generalized §9.2 from "Personal Scanner" to all device classes.

§11 renamed Webhooks → Outbound Integrations: added §11.8 Linked-Service Broker — synchronous device→Identity→product authorize call returning an in-band allow/deny; identity_assertion JWT (JWKS-verified, no stored secret); timeout / circuit-breaker / fail_mode (default closed); idempotency + jti replay. Demoted identification.complete to audit-only; added device.transaction.completed.

§13 API: added POST /v1/device/transactions, /v1/device/signup, /signup/verify, /consent, /enroll (all mTLS), /v1/linked-services CRUD, and PUT /v1/devices/{id} binding. Removed public /v1/identify (now an internal broker step). §13.4 swapped the identify response for the device-transaction response (no user_id returned to the device).

Tenancy (§4): Link Wallet + Link Access are now products within one Link Holdings tenant (shared user + palm namespace — "enroll once, used everywhere"); §4.6/§4.7 reconciled; resolved the §4.7 open question on vendor-namespace isolation via per-tenant namespace prefix. Added §4.9 Linked Services registry.

Account/palm split (§5, §12): account keyed by mobile, palm_enrolled surfaced cross-surface; added POS signup mode; rewrote §12.2 enrollment paths (consent device/app-direct) and §12.3 transaction flow (device-direct broker). Pinned verify (1:1) vs identify (1:N) in §8.

§16 Data: added linked_services and device_transactions tables; extended devices.

Companion diagrams bumped to v2.8: removed legacy §4.1/§4.2 (old kiosk-enroll / POS-identify, superseded); added device-initiated broker transaction (§4.3) + device enrollment (§4.4); §4 renumbered; all palm sequences rewritten to the BioWave /KZ/* API.

Palm vendor swap: removed Link-HF-Verification / HF Security (and the Suprema/Fujitsu alternatives); X-Telcom BioWave Pass is now the sole palm vendor. §8.4 score model 10→4 elements (IR/RGB × large/small); §8.5/8.6 examples updated; §19.7 error table replaced with the X-Telcom set (no-match is now platform-side); §8.10 duplicate detection re-based on /KZ/query (no similarity_search); palm_provider default → biowave; §16/§17/§18 vendor references collapsed to one. All palm diagrams (§1.3, §4.1–4.4, §6.1, health) rewritten to the BioWave /KZ/* API.
6.7 May 2026 Cert expiry alerting — because the platform does not auto-acquire certs (Pattern B: admin uploads from any source — Let's Encrypt, public CA, corporate CA), proactive alerts are required so an expiring cert is never missed.

§9.2.2 SSL Configuration Management — "Expiry alerts" paragraph expanded into three subsections:
• Three delivery channels: admin console UI banners (existing), email to every user with role='platform_admin' (new), and webhook events on platform-scoped endpoints (new).
• Threshold schedule table — server cert at 30/14/7/1/0 days, platform CA at 60/30/14/7/1/0 days (CA gets a 60-day notice because rotation forces every device to re-pair).
• Idempotency: a daily background job tracks last_alert_threshold_days per cert in platform_secrets so re-uploading the same cert mid-window does not re-spam recipients.

§11.5 Webhook Event Types — new "Platform" section:
platform.server_cert.expiring, platform.server_cert.expired, platform.platform_ca.expiring, platform.platform_ca.expired — fields: kind, fingerprint, expires_at, days_remaining, threshold_days.

§11.6 Webhook Configuration:
• Added scope field to webhook endpoints — tenant (default, existing) or platform (Platform Admin only, receives platform.* events). Platform-scoped endpoints are not visible to tenant admins.

§10.3.2 Audit Events:
• New cert_expiry_alert_sent event per alert delivery ({kind, channel, threshold_days, fingerprint, recipient_count}).
• Tidied server_cert_deleted description (no longer references self-signed-throwaway state, removed in v6.6).
6.6 May 2026 First-run SSL simplification — dropped the self-signed throwaway HTTPS cert at first boot; the backend now serves plain HTTP until an admin uploads a cert. Matches the conventions of GitLab, Grafana, Mattermost, Sentry self-hosted.

§9.2.2 SSL Configuration Management — "First-run SSL setup" paragraph rewritten:
• On a fresh install with empty platform_secrets, the backend listens on plain HTTP. No self-signed throwaway cert.
• The Platform Admin (env-seeded; see §3.6) signs in over HTTP, is forced to change the initial password, and uploads the server TLS cert via the SSL Settings page.
PUT /v1/admin/ssl/server-cert persists the cert and returns 200 OK with restart_scheduled: true when transitioning from HTTP. The backend exits the process after the response flushes; the orchestrator (systemd, Docker restart: always, k8s) restarts it. The second boot reads platform_secrets and launches uvicorn in HTTPS mode.
• Steady-state cert rotations (HTTPS → HTTPS) are unchanged — they use SIGHUP for zero-downtime reload.
• Dropped the browser-untrusted-cert-warning click-through note.

Companion diagrams bumped to v2.7:
• §5.4.1 First-Run SSL Setup mermaid rewritten with an explicit "Orchestrator" participant and a process-restart step between the upload response and the HTTPS reload step. Browser-warning language removed.
6.5 May 2026 Bootstrap-flow simplification — dropped the "bootstrap admin" / "bootstrap mode" concept; aligned with the standard self-hosted-vendor pattern (GitLab, Grafana, Mattermost): the regular Platform Admin is env-seeded on first boot, logs in via the normal flow, and uploads SSL through the SSL Settings page.

§3.6 Role Assignment:
• Added "First Platform Admin (initial deploy)" paragraph documenting env-var seeding (PLATFORM_ADMIN_EMAIL, PLATFORM_ADMIN_INITIAL_PASSWORD) with must_change_password=true; env vars read only when no Platform Admin exists.

§9.2.2 SSL Configuration Management:
• Replaced "Bootstrap status endpoint" + "Bootstrap mode" paragraphs with a single "First-run SSL setup" paragraph: backend serves self-signed throwaway cert at startup; admin logs in via the normal /v1/auth/login; SSL Settings page renders inline setup wizard when setup_complete=false. Console functionality is fully available during setup — only scanner mTLS endpoints are blocked.

§13.2 Console API:
• Renamed /v1/admin/ssl/bootstrap-status/v1/admin/ssl/status. Response shape changed from {bootstrap_required, steps_remaining} to {server_cert_configured, platform_ca_configured, setup_complete}.
• Auth changed from "Bootstrap auth" to plain Console session (Platform Admin) — no special auth path.

§13.4 Response Metadata:
• Removed bootstrap_required 503 row; replaced with mtls_not_configured (503 only for scanner routes when platform CA is missing — admin endpoints stay reachable).

§3.4 Console Permission Matrix:
• Collapsed "Run bootstrap setup" row into "Manage platform SSL certs" row.

§2 Glossary:
• Removed "Bootstrap mode" entry (concept no longer exists).

Removed from the spec entirely:
/v1/auth/bootstrap/login endpoint
• "Bootstrap admin" as a distinct role
• "Bootstrap mode" as a distinct operational mode

Companion diagrams bumped to v2.6:
• §5.4.1 renamed "Bootstrap Mode (First Run)" → "First-Run SSL Setup". Rewrote the mermaid flow: seeds Platform Admin from env, admin logs in via normal /v1/auth/login, forced password change, SSL Settings page renders inline setup wizard until setup_complete=true. No separate bootstrap login path. Same 4 participants kept (Admin, Console, Backend, DB).
6.4 May 2026 Consistency sweep — full-document audit closed gaps between §9.2 mTLS / SSL spec, the API spec (§13), audit events (§10.3.2), and supporting sections.

§13.2 Console API:
• Added new "Platform SSL / Certificate Management" sub-table with 10 endpoints: server-cert (GET/PUT/DELETE), ca-cert (GET/PUT) + generate/regenerate (POST), device-policy (GET/PUT), and bootstrap-status (GET).

§13.1 Integrator API:
/v1/devices/pair row now documents the request body shape (pairing_code, csr, device_info with hardware_id) and response (device_id, certificate, ca_chain, expires_at, status).
/v1/devices/renew row now documents the request body (csr) and response shape; notes that the old cert fingerprint goes to the denylist on success.

§13.4 Response Metadata:
• Added a new "Common Error Responses" table covering cert-related error codes: pairing_code_invalid, pairing_rate_limited, csr_invalid_algorithm, csr_invalid_extensions, csr_signature_invalid, device_revoked, pem_invalid, cert_key_mismatch, regenerate_confirm_required, and bootstrap_required (503 during bootstrap mode).

§9.2.2 SSL Configuration Management:
• Added "Bootstrap status endpoint" paragraph documenting GET /v1/admin/ssl/bootstrap-status (used by the admin console's bootstrap wizard).

§10.3.2 Audit Events:
• Added 5 SSL-config audit events (server_cert_uploaded, server_cert_deleted, platform_ca_generated, platform_ca_regenerated, device_policy_changed).
• Added 3 high-severity events the frontend already references but the PRD did not define: device_certs_bulk_revoked, platform_admin_added, tenant_deleted.

§3.4 Console Permission Matrix:
• Added 3 rows: "Manage platform SSL certs", "Configure device cert policy", "Run bootstrap setup" — all Platform Admin only.

§3.9 Security Model:
• Added 5 mTLS-era attack rows: scanner identity spoofing, stolen device cert, platform CA private key compromise, pairing replay/impersonation, cross-tenant access via stolen cert.

§2 Glossary:
• Added 6 entries: PKI, Platform CA, CSR, SAN URI, StrongBox, Bootstrap mode.

§16 Data Architecture:
• Added platform_secrets to the Link Identity backend's data stack diagram with a follow-up paragraph describing the table's role (singleton-by-kind rows for server cert + platform CA; DB-engine encryption-at-rest is the security boundary).
6.3 May 2026 Documentation restructure — diagrams file is now mermaid-only; all reference and prose content lives in the PRD.

Expanded §9.2.1 (mTLS Server Config):
• Added "Handshake mechanics on authenticated endpoints" paragraph describing the full TLS layer → middleware chain (ssl_cert_reqs=CERT_OPTIONAL, CertificateRequest/CertificateVerify, denylist validation, app-layer status check).
• Added "Key design properties of the mTLS layer" bullets — identity-in-cert (no session table), TLS layer as auth boundary, per-request devices.status check as defense-in-depth, implicit tenant isolation via SAN URI.

New PRD appendix sections:
• §19.6 — Scanner Client Implementation Reference (Android): hardware-backed keypair generation (KeyPairGenerator + KeyGenParameterSpec, StrongBox requirement, alias naming), CSR construction via Bouncy Castle with ContentSigner wired to StrongBox-held key, cert storage via OkHttp SSLSocketFactory, renewal lifecycle with alias rotation, loss-of-key recovery semantics.
• §19.7 — X-Telcom BioWave Pass Error Codes (migrated from diagrams Appendix B; cross-refs updated to PRD §8.11 for set_query_type restrictions).
• §19.8 — Nafath Status Codes (migrated from diagrams Appendix C).
• §19.9 — Tenant Config Checks in Flows (migrated from diagrams Appendix D).

Companion diagrams bumped to v2.3:
• Removed prose intro and "Key properties" list from §5.1.3 — content merged into PRD §9.2.1.
• Removed "Scanner-side implementation reference" prose block from §5.1 — content migrated to PRD §19.6, with a one-line pointer left behind.
• Removed §5.4 intro paragraph (redundant with PRD §9.2.2).
• Removed Appendix A "Audit Events Summary" (redundant with PRD §10.3.2 — authoritative copy).
• Removed Appendices B, C, D (migrated to PRD §19.7–19.9).
• Removed "End of Diagrams Document" footer.
6.2 May 2026 Added §9.2.1 — Certificate Authority and CSR Signing:
• Two-PKI model (server TLS PKI + platform CA PKI).
• Platform CA stored in platform_secrets DB table.
• Cert profile: ECDSA P-256, 90-day validity, SAN URI urn:link:tenant:{tenant_id}:device:{device_id}.
• CSR validation rules.
• Server config: CERT_OPTIONAL + route whitelist for /v1/devices/pair.
• Revocation via fingerprint denylist.
• Recovery paths: half-pairing, hardware key loss, clock drift.
• NTP requirement.

Added §9.2.2 — SSL Configuration Management:
• Admin endpoints under /v1/admin/ssl/* for server cert upload, platform CA generate/upload/regenerate, device cert policy.
• Bootstrap mode for first-run setup.

Updated §9.2 preamble to make TLS termination at the application layer explicit and cross-reference the new subsections.
• Added hardware_id to the /v1/devices/pair payload (§9.2 step 4).

Companion diagrams bumped to v2.2:
• Fixed pairing-code spec drift (9 alphanumeric chars, ~47 bits entropy; example updated; pairing_code_hash terminology aligned with PRD).
• Expanded §5.1 (Pairing) — explicit rate-limit step, 4 separate CSR validation steps (PoP, algorithm, strip DN, reject privileged extensions), explicit canonical cert template construction.
• Expanded §5.1.1 (Renewal) — explicit mTLS handshake at start, SAN URI extraction, atomic BEGIN/COMMIT for cert rotation + denylist insert.
• Expanded §5.1.2 (Revocation) — atomic transaction shown, TLS-layer rejection mechanism (handshake aborts before app), in-flight connection caveat.
• Added new §5.1.3 (mTLS Handshake on Authenticated Endpoints) — TLS layer → middleware → DB status check → handler, including the "Key properties" rationale for why identity-in-cert + per-request status check defends against denylist propagation lag.
• Added scanner-side implementation reference (Android) after §5.1 mermaid — covers KeyPairGenerator + KeyGenParameterSpec (StrongBox-backed P-256), Bouncy Castle JcaPKCS10CertificationRequestBuilder with a ContentSigner wired to the StrongBox key, cert storage via OkHttp SSLSocketFactory, alias rotation on renewal, and loss-of-key recovery.
6.1 Apr 2026 Aligned palm verification with the palm vendor's cloud API:
• Renamed the palm vendor adapter.
• Added §8.4 Score Model (10-element scores/thresholds with palm_match_policy per tenant).
• Replaced single confidence float with scores arrays in §8.5/8.6.
• Added §8.10 Pre-Enrollment Duplicate Detection (similarity check, configurable reject/flag).
• Added §8.11 Palm Type Restrictions (set_query_type per user with admin endpoint).
• Added §8.12 Operational (vendor health monitoring, threshold configuration).
• Added challenge-based personal scanner enrollment to §9.2 (parallel to kiosk path).
• Added §4.7 open question on tenant isolation for global vendor namespace.
• Added 7 new audit events to §10.3.2 (palm_enrollment_failed, palm_duplicate_detected, palm_restriction_set, palm_thresholds_updated, palm_vendor_unhealthy, palm_vendor_unauthorized, palm_vendor_version_change).
• Added admin endpoints /v1/admin/palm/thresholds, /v1/admin/palm/health, and /v1/users/{id}/palm-restriction to §13.
• Added new tenant settings: palm_match_policy, palm_duplicate_check_enabled, palm_duplicate_action.
6.0 Mar 2026 Full restructure:
• Merged Trust/Actors with Roles (§3).
• Merged Multi-Tenancy with Configuration (§4).
• Moved Compliance before Webhooks (§10–11).
• Moved User Journeys after all capabilities (§12).
• Labeled KYC (§7), SMS, SSO as post-MVP.
• Absorbed Core Capabilities into Appendix.
• Dropped redundant §3.2 Actors table.
• All content preserved, no deletions.
5.5 Mar 2026 Added Console API:
• §14.2 (MVP) with tenant config CRUD, platform admin tenant management, user list/search/suspend/reactivate, audit log query, dashboard stats.
• §14.3 (Post-MVP) for KYC sessions, SMS config, archive search, consent records.
• Renamed §14.1 to "Integrator API".
• Clarified webhook delivery is direct HTTP with retries (no queue).
5.4 Mar 2026 Expanded §16 (Webhooks) with full specification:
• Delivery contract, payload structure with passthrough metadata.
• HMAC-SHA256 signing security, retry policy.
• 14 event types (added user.suspended, user.reactivated, verification.failed).
• Per-endpoint configuration, webhook management API.
• Added §6.5 (Webhook Signing Secrets).
• Added /v1/webhooks endpoints to §14.1.
• Renumbered §6.6–6.13.
5.3 Mar 2026 Restructured §4 (Roles & Access Control):
• Added §4.1 Identity Domains separating console users from managed identities.
• Split permission matrix into §4.3 Console, §4.4 API, §4.5 End User Endpoints.
• Clarified end users only access auth endpoints directly — all other operations go through integrator backends.
• Fixed §5.2 deletion wording, §12.2 consent wording.
• Added audit events: client_auth_failed, challenge_created, token_refresh_failed to §15.3.2.
5.2 Mar 2026 • Added OAuth Client Management (§6.4) with client entity, secret model (1 secret, shown once, bcrypt-hashed), tenant-scoped equal-permission clients, lifecycle (create/regenerate/revoke).
• Added /v1/clients API endpoints to §14.1.
• Added client audit events to §15.3.2.
• Renumbered §6.5–6.12.
5.1 Mar 2026 • Added Roles & Access Control (§4) with 5-role RBAC model and permission matrix.
• Added Multi-Tenancy Architecture (§11) with isolation model, tenant lifecycle, provisioning, and cross-tenant rules.
• Renumbered to 22 sections.
5.0 Mar 2026 Full restructure: 20-section layout.
• Merged stubs (Actors, Initiation Patterns, Android Scanner).
• Consolidated compliance (Consent + Audit + Retention).
• Moved Glossary to front.
• Fixed tenant type contradiction.
• Standardized event types.
4.3 Feb 2026 Verification enforcement, consent management
4.0 Feb 2026 Unified tenant model, compliance features
3.7 Feb 2026 Palm verification ports & adapters, pluggable vendors
3.6 Feb 2026 KYC integration, repo structure
3.5 Feb 2026 Refresh tokens, social login