{"id":50249929,"url":"https://github.com/egorkhaklin/polaris-id","last_synced_at":"2026-06-10T02:00:53.902Z","repository":{"id":358235097,"uuid":"1240571632","full_name":"EgorKhaklin/polaris-id","owner":"EgorKhaklin","description":"National identity-token reference implementation. Post-quantum signing, zero-knowledge defaults, compulsion-resistant by construction.","archived":false,"fork":false,"pushed_at":"2026-06-06T09:10:57.000Z","size":8449,"stargazers_count":2,"open_issues_count":10,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-06T10:21:50.474Z","etag":null,"topics":["anti-coercion","audit-log","cryptography","flask","identity","identity-management","merkle-tree","mfa","plonky2","post-quantum-cryptography","postgresql","rust","snark","swarm-intelligence","webauthn","zero-knowledge-proofs"],"latest_commit_sha":null,"homepage":"https://github.com/EgorKhaklin/polaris-id/blob/main/MISSION.md","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/EgorKhaklin.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":"ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":"NOTICE","maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"EgorKhaklin"}},"created_at":"2026-05-16T09:48:20.000Z","updated_at":"2026-06-06T09:02:47.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/EgorKhaklin/polaris-id","commit_stats":null,"previous_names":["egorkhaklin/polaris"],"tags_count":87,"template":false,"template_full_name":null,"purl":"pkg:github/EgorKhaklin/polaris-id","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EgorKhaklin%2Fpolaris-id","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EgorKhaklin%2Fpolaris-id/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EgorKhaklin%2Fpolaris-id/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EgorKhaklin%2Fpolaris-id/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/EgorKhaklin","download_url":"https://codeload.github.com/EgorKhaklin/polaris-id/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EgorKhaklin%2Fpolaris-id/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34133404,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-10T02:00:07.152Z","response_time":89,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["anti-coercion","audit-log","cryptography","flask","identity","identity-management","merkle-tree","mfa","plonky2","post-quantum-cryptography","postgresql","rust","snark","swarm-intelligence","webauthn","zero-knowledge-proofs"],"created_at":"2026-05-27T01:10:11.827Z","updated_at":"2026-06-10T02:00:53.853Z","avatar_url":"https://github.com/EgorKhaklin.png","language":"Python","funding_links":["https://github.com/sponsors/EgorKhaklin"],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n\u003cimg src=\"assets/polaris_logo_clean.png\" alt=\"Polaris\" width=\"280\"\u003e\n\n# POLARIS\n\n### A working national identity infrastructure.\n\n_Cryptographically signed. Audit-of-record by construction. Compulsion-resistant by design._\n\n\u003e _Fixus inter mutabilia._ \u0026nbsp; Fixed amid the mutable.\n\n[![CI](https://img.shields.io/github/actions/workflow/status/EgorKhaklin/polaris-id/ci.yml?branch=main\u0026label=CI\u0026logo=githubactions\u0026logoColor=white\u0026style=flat-square)](https://github.com/EgorKhaklin/polaris-id/actions/workflows/ci.yml)\n[![Release](https://img.shields.io/github/v/release/EgorKhaklin/polaris-id?label=release\u0026color=2b5797\u0026style=flat-square)](https://github.com/EgorKhaklin/polaris-id/releases/latest)\n[![Last commit](https://img.shields.io/github/last-commit/EgorKhaklin/polaris-id?color=success\u0026style=flat-square)](https://github.com/EgorKhaklin/polaris-id/commits/main)\n\n[![Python 3.12](https://img.shields.io/badge/python-3.12-3776AB?logo=python\u0026logoColor=white\u0026style=flat-square)](polaris_web/)\n[![PostgreSQL 16](https://img.shields.io/badge/postgres-16-336791?logo=postgresql\u0026logoColor=white\u0026style=flat-square)](polaris_sql/)\n[![Rust](https://img.shields.io/badge/rust-nightly-DEA584?logo=rust\u0026logoColor=white\u0026style=flat-square)](polaris_zk/)\n[![Plonky2](https://img.shields.io/badge/zk--snark-plonky2-8957e5?style=flat-square)](polaris_zk/src/lib.rs)\n[![WebAuthn MFA](https://img.shields.io/badge/auth-WebAuthn%20MFA-1f883d?logo=webauthn\u0026logoColor=white\u0026style=flat-square)](polaris_web/webauthn_auth.py)\n\n\n**Now shipping [the latest release](https://github.com/EgorKhaklin/polaris-id/releases/latest)** \u0026nbsp;·\u0026nbsp; post-quantum · zero-knowledge · compulsion-resistant \u0026nbsp;·\u0026nbsp; one double-click to launch\n\n[**System map**](docs/reference/SYSTEM-MAP.md) · [**Conventions**](docs/CONVENTIONS.md) · [**Constitution (MISSION.md)**](MISSION.md) · [**Backlog (ROADMAP.md)**](ROADMAP.md) · [**Audit-of-record (CHANGELOG.md)**](CHANGELOG.md) · [**Agent runbook (CLAUDE.md)**](CLAUDE.md)\n\n**The system** \u0026nbsp; [The hard parts](#the-hard-parts) · [Token model](#the-token-model) · [Architecture](#architecture) · [Cryptography](#cryptography) · [How it differs](#how-it-differs-from-existing-identity-systems)\n\n**Proof of life** \u0026nbsp; [Quickstart](#quickstart) · [What you get](#what-you-get) · [The trick](#the-trick) · [Tour](#tour) · [Tests](#tests) · [License](#license)\n\n\u003c/div\u003e\n\n---\n\n## What this is\n\nAmericans currently carry six to eight credentials that do not talk to each other: driver's license, passport, Social Security card, Real ID, voter registration, health insurance card, and a thickening pile of agency-specific identifiers. Each is a different artifact, signed by a different authority, secured to a different standard, with no shared revocation path and no shared audit trail.\n\nPolaris consolidates them into **one physical token per person**, signed under post-quantum cryptography, with **context-scoped verification** (banking versus voting versus healthcare are different events with different disclosure rules) and **zero-knowledge defaults** (the typical verification stores no token identifier at all).\n\nThis repository is a **working reference implementation**: 28 schema tables, 14 stored procedures, a Flask web application that exercises every use case, a Plonky2 ZK-SNARK prover in Rust, WebAuthn-MFA operator authentication, an operational atlas with a live globe, and a self-healing macOS launcher that gets all of it running from a single double-click.\n\nIt is not a slide deck. It runs.\n\nThe system lives in [`polaris_sql`](polaris_sql/), [`polaris_web`](polaris_web/), [`polaris_cli`](polaris_cli/), [`polaris_zk`](polaris_zk/). Its C1-C10 invariants are machine-checked by [`polaris_checks`](polaris_checks/) (a flat layer of plain check functions).\n\n---\n\n## The hard parts\n\nConsolidating the cards is the easy half. The interesting half is what happens when an adversary shows up. Polaris answers six of them by construction.\n\n| The threat | What it looks like in practice | How Polaris answers it | Where |\n|---|---|---|---|\n| **Cryptographic compulsion** | \"Sign this transaction or I break your fingers.\" The holder cannot refuse without injury. | A second secret produces an indistinguishable verification that silently records a DuressEvent. The operator's screen reveals nothing. | [duress-codes](DEVNOTES/ships/duress-codes.md) ‎  ‎ ‎  UC-12 |\n| **Catastrophic loss** | Token lost, holder unidentified, no way to prove who they are without the artifact. | Two-phase recovery ceremony (initiate then complete) gated by four CHECK constraints and an admin-only second key. | [recovery-ceremony](DEVNOTES/ships/recovery-ceremony.md)   UC-9 |\n| **Quantum migration** | Today's signing algorithms become broken overnight when a quantum computer arrives. | Multi-signature transitional state: a token can be signed under classical AND post-quantum algorithms simultaneously, with a hard rule that exactly one is active. | [multi-sig-migration](DEVNOTES/ships/multi-sig-migration.md)   UC-6 |\n| **Issuer concentration** | One agency can issue tokens that masquerade as any other agency's. | Explicit-only federation: no transitive trust. Every cross-agency verification gates on an active AgencyTrustAttestation row. | [federation](DEVNOTES/ships/federation.md)  UC-10 |\n| **Public auditability without privacy loss** | \"Prove this token was in the ledger\" without revealing which one. | Plonky2 ZK-SNARK over a Merkle commitment. The proof reveals nothing about the leaf. | [zk-snark](DEVNOTES/ships/zk-snark.md)  ‎     UC-11 |\n| **Issuer overreach** | An agency revokes tokens at industrial scale outside policy. | Per-agency revocation-rate ceiling enforced by trigger. Sanctioned by the IssuerDiscretionPolicy row, audited by `pg_advisory_xact_lock`. | [issuer-discretion](DEVNOTES/ships/issuer-discretion.md)   UC-8 |\n\nEvery row has a defender's claim, an attacker's optimal play, an equilibrium analysis, a documented second-best attack, and an enforcement trace at the schema level.\n\n---\n\n## The token model\n\nAn IdentityToken is a row in Postgres. The physical card carries the cryptographic serial; the row carries everything else.\n\n```\nIdentityToken\n├── token_value             VARCHAR(128)   UNIQUE      canonical cryptographic serial\n├── physical_serial         VARCHAR(64)    UNIQUE      hardware serial of the card\n├── hardware_model          VARCHAR(50)                manufacturer / model\n├── biometric_binding_type  enum                       NONE · FINGERPRINT · FACE · IRIS\n├── liveness_check_type     enum                       PASSIVE · ACTIVE_CHALLENGE · MULTI_MODAL\n├── individual_id           → Individual               the person\n├── issuing_agency_id       → Agency                   who issued it\n├── algorithm_id            → CryptographicAlgorithm   ML-DSA-65 by default\n├── predecessor_token_id    → IdentityToken (self)     the succession chain\n├── activation_sequence     INTEGER ≥ 1                which token in the lineage\n├── status                  enum                       ACTIVE · RESERVE · DORMANT · REVOKED · LOST · EXPIRED\n├── issued_date · activated_date · expiration_date\n└── duress_code_hash        VARCHAR(255) NULL          the second secret (optional)\n```\n\nThe shape carries the policy. Four invariants worth naming:\n\n- **One ACTIVE row per individual.** Enforced by a partial unique index on `(individual_id) WHERE status = 'ACTIVE'`, not by application logic. Replacing a token means walking the lineage forward, not opening a second row. That is constraint **C3** in the constitution, and it survives every restore from backup because it lives in the index, not in code.\n- **Algorithm by reference, not literal.** The signing algorithm is a foreign key to `CryptographicAlgorithm`, a first-class entity carrying `quantum_resistant`, `nist_standard`, and `deprecation_date`. There is no hardcoded crypto anywhere in the codebase. Adding ML-DSA-87 tomorrow is `INSERT INTO`, not `git push`. That is constraint **C7**.\n- **Succession is a chain, not an event.** `predecessor_token_id` is self-referential; the full lineage from a person's first issuance to their current token is one recursive CTE. Recovery, replacement, and post-quantum migration all add a new row pointing at the predecessor; nothing is overwritten.\n- **Duress is observable only to the audit trail.** If a holder types the duress code under coercion, the verification looks identical to a normal one on every operator-visible surface. A `DuressEvent` row appears in the audit-of-record; the operator's screen reveals nothing. That is constraint **C6 + the anti-coercion vocation** working together.\n\nThe `CREATE TABLE` is in [`polaris_sql/01_schema.sql`](polaris_sql/01_schema.sql). Every column is documented; every CHECK constraint has a paired test.\n\n---\n\n## Architecture\n\nFour layers. The check layer reads but never writes the operational layer. The ZK prover is a subprocess, not a service. WebAuthn FIDO2 is the only authentication path for human operators; passwords alone cannot reach the admin or auditor roles.\n\n```\n        ┌─────────────────────────────────────────────────────────────┐\n        │                       CHECK LAYER                           │\n        │   polaris_checks — flat C1-C10 invariant checks             │\n        │   (CSP · one-active-token · append-only AoR · crypto-as-    │\n        │    data · FK discipline · secrets · ZK two-witness · …)     │\n        │   plain check_*(repo_root) functions; `run` gates CI        │\n        └─────────────────────────┬───────────────────────────────────┘\n                                  │   reads (no writes)\n        ┌─────────────────────────▼───────────────────────────────────┐\n        │                       APPLICATION                           │\n        │     Flask (67 routes)  ·  Atlas globe  ·  WebAuthn MFA      │\n        │     Dashboard  ·  /sql console  ·  Sanctum tooling          │\n        └──────────┬──────────────────────────┬───────────────────────┘\n                   │                          │\n        ┌──────────▼─────────┐    ┌───────────▼──────────────────────┐\n        │  SCHEMA (Pg 16)    │    │   ZK PROVER (Rust nightly)       │\n        │  26 tables         │    │   Plonky2 SNARK · Merkle-incl.   │\n        │  14 stored procs   │    │   /api/zk/epoch/close            │\n        │  9 AoR by trigger  │    │   /api/zk/verify                 │\n        └──────────┬─────────┘    └──────────────────────────────────┘\n                   │\n                   │  signs with\n                   ▼\n        ┌───────────────────────────────────────────────────────────┐\n        │                 POST-QUANTUM SIGNATURES                   │\n        │   ML-DSA-65 (FIPS 204, default)  ·  SLH-DSA (FIPS 205)    │\n        │   ML-DSA-87 (high-assurance)  ·  ECDSA-P256 (legacy/audit)│\n        └───────────────────────────────────────────────────────────┘\n```\n\nEach layer is independently buildable. The schema loads from `00_load_all.sql` against an empty Postgres. The application boots from `app.py` against the loaded schema. The ZK prover compiles under `cargo +nightly build --release` against the same machine. The check layer (`polaris_checks`) is a read-only set of plain functions that gate CI; it survives any operational restart unchanged.\n\nThe constraint that holds this together is **C1: audit-of-record**. Ten instances (nine schema, one filesystem) record every meaningful operation at the moment it happens. Nothing in the system reconstructs history after the fact; if it isn't written when it occurs, it doesn't exist.\n\n---\n\n## Cryptography\n\nThe signing-algorithm registry seeds with five rows. The operational default is **ML-DSA-65**: the NIST-standardized Module-Lattice Digital Signature Algorithm, FIPS 204, Level 3 security, finalized in 2024.\n\n```\nalgorithm        family     PQ    NIST           sec   public-key   signature\n─────────────────────────────────────────────────────────────────────────────\nML-DSA-65        ML-DSA      ✓    FIPS 204       192     1,952 B       3,309 B   ◀ default\nML-DSA-87        ML-DSA      ✓    FIPS 204       256     2,592 B       4,627 B   high-assurance\nSLH-DSA-128s     SLH-DSA     ✓    FIPS 205       128        32 B       7,856 B   hash-based hedge\nSLH-DSA-256s     SLH-DSA     ✓    FIPS 205       256        64 B      29,792 B   hash-based, max\nECDSA-P256       ECDSA            FIPS 186-4     128        64 B          72 B   LEGACY · sunsets 2027-12-31\n```\n\nThree things are worth noting about this list:\n\n- **The default algorithm is already post-quantum.** ML-DSA-65 is the algorithm new tokens are issued under on day one. There is no \"we will migrate when quantum arrives\" deferral; the migration target is the current default. (The real ML-DSA-65 *signature bytes* are produced with `POLARIS_USE_REAL_PQC=1`; with the flag off the default build records a deterministic placeholder, see the liboqs note below.) ECDSA-P256 is retained only because pre-PQ audit queries need to resolve the algorithm by foreign key.\n- **SLH-DSA is a diversity hedge.** Both ML-DSA and SLH-DSA are NIST-standardized post-quantum signature schemes, but they rest on entirely different cryptographic assumptions: ML-DSA on lattice problems, SLH-DSA on hash function security alone. If one family is broken, the other is independent. The cost of the hedge is signature size (29.8 KB for SLH-DSA-256s vs 3.3 KB for ML-DSA-65).\n- **The cost of post-quantum is the signature size.** A 3,309-byte ML-DSA-65 signature is roughly 46× larger than a 72-byte ECDSA signature. Polaris treats that cost as a property of the artifact, not as a problem to optimize away.\n\n**Migration (UC-6 · `/uc6/migrate-algorithm`)** is a multi-signature transitional state. A token can carry **both** a classical and a post-quantum signature simultaneously during cutover, with a constraint that exactly one is operationally active. Tokens migrate one-at-a-time on a per-individual schedule; the cutover writes a `KeyMigration` row that the audit trail can replay. The constraint that prevents a half-migrated state from serving traffic is enforced at the database, not in code.\n\nThe PQC integration uses [liboqs](https://github.com/open-quantum-safe/liboqs) via the `oqs` Python binding, gated by `POLARIS_USE_REAL_PQC=1`. With the flag off, the system uses a deterministic placeholder so property tests remain reproducible across machines without liboqs installed. Activation is operator-side; see [`scripts/polaris-pqc-status.sh`](scripts/polaris-pqc-status.sh).\n\nThe zero-knowledge surface is independent of the signing algorithm. **Plonky2** in [`polaris_zk/src/lib.rs`](polaris_zk/src/lib.rs) proves Merkle-tree inclusion against epoch commitments published at [`/epochs`](polaris_web/templates/epochs_list.html). The proof reveals nothing about the leaf; it answers only \"was this token in the ledger at epoch N.\" The Rust binary is a subprocess called by [`polaris_web/zk.py`](polaris_web/zk.py); the Flask app degrades gracefully without it (every page serves, every UC-1..UC-12 flow works, only `/api/zk/epoch/close` and `/api/zk/verify` go quiet).\n\n---\n\n## How it differs from existing identity systems\n\nThere is no shortage of identity infrastructure in the world. The question is what Polaris does that the existing deployed systems do not.\n\n| System | National-scope issuance | Post-quantum operational default | Zero-knowledge default | Compulsion-resistant primitive | Append-only AoR at schema |\n|---|:---:|:---:|:---:|:---:|:---:|\n| **Real ID** (US, 2005 act, fully enforced 2025) | ✓ | ✗ | ✗ | ✗ | ✗ |\n| **mDL / ISO 18013-5** (mobile driver's license) | ✓ | ✗ | partial | ✗ | ✗ |\n| **Aadhaar** (India, 1.3B+ enrolled) | ✓ | ✗ | ✗ | ✗ | partial |\n| **e-Estonia** (e-ID + e-Residency) | ✓ | ✗ | ✗ | ✗ | partial |\n| **W3C DIDs / VCs** (spec, decentralized) | ✗ | method-dependent | ✓ | ✗ | n/a |\n| **Polaris** (this repo) | ✓ | ✓ ML-DSA-65 | ✓ Plonky2 + R6 redaction | ✓ DuressEvent | ✓ 9 schema instances |\n\nA few of the contrasts are worth narrating instead of tabling.\n\n**Real ID** standardizes the document and the source-of-truth check. It does not standardize a verification protocol; the card is signed by the printer, not by a key. There is no cryptographic identity at all, no shared revocation path, and no audit trail beyond what each individual DMV chooses to retain.\n\n**mDL (ISO/IEC 18013-5)** is the closest deployed system in spirit. It already does selective disclosure (\"prove the holder is over 21 without revealing their address\") and is signed cryptographically. What mDL does not do today is post-quantum signatures, a formal compulsion-defense primitive, or a constitutional layer governing how the issuer itself behaves over time.\n\n**Aadhaar** has biometric binding at national scale; its strength is also its weakness. The biometric templates live in a centralized authority and can be queried by it. Polaris treats biometric binding as a per-token attribute with an explicit enrollment witness agency, not as a population-scale biometric database. The system can answer \"is this token bound to a fingerprint\" without ever holding the fingerprint outside the holder's possession.\n\n**W3C DIDs and Verifiable Credentials** are spec, not system. They support the verification model Polaris uses (cryptographic identifiers, selective disclosure, federation-by-attestation), but they do not address national-scope issuance, biometric binding, or the operational substrate that an issuing authority would need to actually run one. Polaris fills the substrate; it could in principle emit VCs as a representation format.\n\n**e-Estonia** is the existing deployed system most-similar in ambition. Its cryptography is classical (ECDSA on the e-ID card, RSA in older infrastructure); a platform-level migration path to post-quantum is not yet specified. The system has no compulsion-defense primitive at the protocol level.\n\nPolaris's contribution is not novelty in any single primitive. It is the **assembly**: a national-scope issuance model, a post-quantum operational default, zero-knowledge defaults on verification, a duress-code primitive built into the verification flow, and an append-only audit-of-record enforced at the database trigger level — every one of which is machine-checked at the schema level rather than asserted in prose.\n\n---\n\n## Quickstart\n\nYou need a Mac with [Docker Desktop](https://www.docker.com/products/docker-desktop) installed. That is the only prerequisite.\n\n```bash\ngit clone \u003cthis-repo\u003e polaris\ncd polaris\n./Polaris.command            # or: ./polaris_mac_launch.sh up\n```\n\nThe first run pulls Postgres 16, builds the Flask image, loads the schema, runs the SQL self-tests, and opens your browser at `http://localhost:2222`. Subsequent launches take roughly ten seconds.\n\nSign in with one of three seeded roles:\n\n```\nadmin     ·  Admin@123!     full access + SQL console + Sanctum tooling\noperator  ·  Operator@123!  issue / activate / bind tokens\nauditor   ·  Auditor@123!   read-only + warrant audits + duress dashboard\n```\n\nClose the browser tab to stop. The launcher is watching the page; when you close it, it tears the stack down automatically.\n\nA full subcommand reference lives in [`docs/operator/INSTALL.md`](docs/operator/INSTALL.md). If anything looks wrong, the launcher carries a read-only diagnostic:\n\n```bash\n./polaris_mac_launch.sh doctor\n```\n\n---\n\n## What you get\n\n```\n                 ┌──────────────────────────────────────────────────┐\n                 │              Polaris in numbers                  │\n                 │              (current as of v9.63)               │\n                 ├──────────────────────────────────────────────────┤\n                 │  26 schema tables                                │\n                 │  14 stored procedures (UC-1 .. UC-12)            │\n                 │  67 HTTP routes (incl. /auth/webauthn/*)         │\n                 │  C1-C10 invariants, machine-checked              │\n                 │  Plonky2 ZK + an independent second witness      │\n                 │  3 agent-contract principles + 1 vocation        │\n                 │  1 double-click to launch                        │\n                 └──────────────────────────────────────────────────┘\n```\n\nAfter login the app lands on the **Dashboard**, which fans out into eight analytical panels covering schema statistics, token status, the authorization matrix, post-quantum migration ratio, verification activity by context, disclosure posture, succession lineage, and the audit trail.\n\nThe **Atlas** (`/atlas`) is the operational investigation surface: a live globe with reticles for every verification and lifecycle event, a four-figure HUD (Active Tokens, Anomalies, Post-Quantum percentage, Zero-Knowledge percentage), and click-through into any token's full record including its predecessor chain.\n\nRoutes for each use case: `/uc1/issue`, `/uc4/activate-reserve`, `/uc5/bind-device`, `/uc6/migrate-algorithm`, `/uc7/warrant-audit`, `/uc8/revoke-token`, `/uc9/recover-identity`, `/duress`, `/anchors`, `/epochs`, `/federation`, and `/sql` (admin / auditor only).\n\n---\n\n## The trick\n\nMost reference implementations of an identity system put their rules in application code, where the next caller can bypass them. Polaris puts them in the **database**, where Postgres enforces them regardless of which client connects:\n\n- **One ACTIVE token per person** is a partial unique index on `(individual_id) WHERE status = 'ACTIVE'` — not an `if` statement. It survives every restore from backup.\n- **The audit-of-record** is a trigger that raises `insufficient_privilege` on any `UPDATE`/`DELETE` of a lifecycle-event table — not a logging convention.\n- **Zero-knowledge** is a CHECK constraint that refuses to store a token id on a `ZERO_KNOWLEDGE` verification — not an application policy.\n\nThose rules are then machine-checked by [`polaris_checks`](polaris_checks/) — a flat layer of plain `check_*(repo_root)` functions, a check per constitutional constraint (C1-C5 and C7-C10 directly; C6 via the redaction-property test) plus a handful of repo-hygiene checks, each with *tested detection correctness* (it provably fails on a broken input). `python3 -m polaris_checks.run` gates CI directly. A check is a check: no framework, no mythology, ~300 legible lines a second engineer reads in minutes.\n\n\u003e Earlier versions carried an elaborate \"cognitive substrate\" — an introspection swarm, a simulated Roman economy, a self-governance apparatus — meant to let an AI agent maintain the system. **v9.55 removed it:** ~18k LOC of apparatus replaced by the flat check layer above. The development record of that arc is preserved in the CHANGELOG and the git history. The principles it served (the constitution) are unchanged; the implementation is simply honest now.\n\n---\n\n## Tour\n\nStart at the file that matches what you came here for.\n\n|   |   |   |\n|---|---|---|\n| **[The architecture](docs/ARCHITECTURE-OVERVIEW.md)** | **[The system map](docs/reference/SYSTEM-MAP.md)** | **[The principles](docs/story/PRINCIPLES.md)** |\n| The four layers and how they connect: the schema, the application, the check layer, and the ZK prover. Read this to see how the pieces fit. | A single page that names every meaningful artifact in the repository and what it is for. Use this when you do not know where to start. | The principles that hold the system together, distilled. Read this before you change anything load-bearing. |\n| **[The schema](polaris_sql/01_schema.sql)** | **[The constitution](MISSION.md)** | **[The agent runbook](CLAUDE.md)** |\n| 26 tables. Start with `IdentityToken` and follow the foreign keys. Append-only invariants enforced at trigger level on nine of them. | C1 through C10. Ten hard constraints the system must never violate, each enforced at the schema level rather than in application code. | If you are an AI agent priming on this project, this is your entry point. |\n| **[The Atlas](polaris_web/static/atlas-globe.js)** | **[The ZK prover](polaris_zk/src/lib.rs)** | **[The CHANGELOG](CHANGELOG.md)** |\n| The operational globe. 1,318 lines of D3 + custom projection logic. Pan, zoom, drag, hover, click-through, viewport-aware decimation. | Plonky2-backed Merkle-inclusion circuit in Rust. Subprocess CLI consumed by `polaris_web/zk.py`. | The full audit-of-record (108K words; pre-v9.24 archive). The curated last-10-ships index lives at `CHANGELOG.md` (~3.7K words). |\n\nFor an exhaustive index of operator and architect documentation, see [`docs/README.md`](docs/README.md).\n\n---\n\n## Tests\n\nFour layers of verification, all run by the launcher's `test` subcommand.\n\n```\n┌─────────────────────────────┬────────┬──────────────────────────────────────────────┐\n│  Layer                      │  Count │  What it covers                              │\n├─────────────────────────────┼────────┼──────────────────────────────────────────────┤\n│  Product tests (DB-backed)  │        │  CHECK constraints, the use cases, every     │\n│  test_app / test_cli /      │        │  Flask route + form, the rate limiter, the   │\n│  test_check_constraints     │        │  atlas API, R6 anti-revealing posture.       │\n│  Property tests (Hypothesis)│   16   │  Adversarial inputs against C1, C2, C3 and   │\n│                             │        │  the M2-12 redaction-proof.                  │\n│  polaris_checks (C1-C10)    │   17   │  One plain check_* per constitutional        │\n│                             │        │  constraint; tested detection correctness;   │\n│                             │        │  `run` gates CI. The flat invariant layer.   │\n└─────────────────────────────┴────────┴──────────────────────────────────────────────┘\n```\n\n```bash\n./polaris_mac_launch.sh test          # full suite, ~60 s\n./scripts/ai-test.sh quick            # skip the slow concurrency + property tests\n./scripts/ai-done.sh                  # pre-ship gate (incl. CM enforcement)\n```\n\nA release is shippable when every layer passes and `ai-done` reports `READY`.\n\n---\n\n## Subcommand reference\n\n```bash\n./polaris_mac_launch.sh                # default; same as 'up'\n./polaris_mac_launch.sh up             # bring up, watch the browser, open it\n./polaris_mac_launch.sh up --detach    # bring up in background and return\n./polaris_mac_launch.sh rebuild        # force clean rebuild (no cache)\n./polaris_mac_launch.sh stop           # graceful shutdown\n./polaris_mac_launch.sh status         # what is running, where\n./polaris_mac_launch.sh doctor         # read-only diagnostic\n./polaris_mac_launch.sh logs           # tail Flask log (default)\n./polaris_mac_launch.sh logs db        # tail Postgres log\n./polaris_mac_launch.sh test           # run the test suite\n./polaris_mac_launch.sh reset          # drop pgdata, keep image\n./polaris_mac_launch.sh nuke           # total wipe: containers + image + volume\n./polaris_mac_launch.sh --port 5050    # alternate host port\n./polaris_mac_launch.sh --native       # native path; Homebrew, no Docker\n./polaris_mac_launch.sh --help         # full help\n```\n\n---\n\n## Building the ZK prover (optional)\n\nThe Rust source for the Plonky2 prover ships in `polaris_zk/`; the compiled binary does not. The Flask app degrades gracefully without it: every page serves, every UC-1..UC-12 flow works, `/epochs` renders historical epochs from the seed. The binary is only needed to **prove or verify new epoch closures** (`/api/zk/epoch/close`, `/api/zk/verify`).\n\n```bash\ncurl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh\nrustup install nightly\ncd polaris_zk \u0026\u0026 cargo +nightly build --release\n```\n\nAfter the build, `polaris_zk/target/release/polaris-zk` exists; the Flask app finds it via the default path. Override with `POLARIS_ZK_BINARY=/your/path/polaris-zk` if you build elsewhere.\n\n---\n\n## License\n\nPolaris is released under the [Apache License, Version 2.0](LICENSE).\n\n```\nCopyright 2026 Egor Khaklin\nLicensed under the Apache License, Version 2.0.\n```\n\nThe license includes an explicit **patent grant** (§3) and **preservation of attribution** (§4). If you build on Polaris — the code, the schema, or the architectural patterns (audit-of-record discipline, the schema-level constraint lattice, the flat invariant-check layer) — retain `LICENSE` and `NOTICE` and the author attribution per §4. Component-level attributions for Plonky2, D3, TopoJSON, and Flask live in [NOTICE](NOTICE).\n\nThe academic project report ([docs/paper/polaris_project_report.pdf](docs/paper/polaris_project_report.pdf) and its TeX source) is part of the same release under the same license.\n\n---\n\n## Attribution\n\nEducational project for **Seton Hill University**, Spring 2026. Notional data only; not a real identity system. All cryptographic algorithm choices reflect current NIST PQC standardization (FIPS 204, FIPS 205) for academic accuracy.\n\nThe constitution lives in [MISSION.md](MISSION.md). The ship history lives in [CHANGELOG.md](CHANGELOG.md).\n\nIf you read one document after this one, read [MISSION.md](MISSION.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fegorkhaklin%2Fpolaris-id","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fegorkhaklin%2Fpolaris-id","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fegorkhaklin%2Fpolaris-id/lists"}