- Swift 39.5%
- Assembly 22.2%
- C 16.1%
- C++ 14.9%
- Nix 1.8%
- Other 5.2%
| .codex | ||
| .forgejo | ||
| Android | ||
| API | ||
| Apple | ||
| config | ||
| docs | ||
| evolution | ||
| finances | ||
| forgejo | ||
| gradle | ||
| Linux/App | ||
| nixos | ||
| notes | ||
| org | ||
| Packages | ||
| records | ||
| Scripts | ||
| secrets | ||
| services | ||
| skills | ||
| store-metadata | ||
| Web | ||
| .envrc | ||
| .git_allowed_signers | ||
| .gitattributes | ||
| .gitignore | ||
| .gitmodules | ||
| .lfsconfig | ||
| .swiftlint.yml | ||
| AGENTS.md | ||
| biome.json | ||
| build.gradle.kts | ||
| bun.lock | ||
| bunfig.toml | ||
| CONSTITUTION.md | ||
| CONTRIBUTORS.md | ||
| contributors.nix | ||
| flake.lock | ||
| flake.nix | ||
| gradle.properties | ||
| gradlew | ||
| gradlew.bat | ||
| Makefile | ||
| package.json | ||
| README.md | ||
| secrets.nix | ||
| settings.gradle.kts | ||
key.store
key.store is an autonomous, open-source password manager that treats its codebase, build farm, and infrastructure as a single sovereign kernel. The long-term goal—spelled out in the recorded genesis message and transcribed in genesis.txt—is to let a self-hosted forge nurture a “crystalline artifact”: a Swift-based password manager with transparent provenance, reproducible builds, and agents that can evolve it safely. The intent is codified in the key.store constitution; every plan or proposal should trace back to it.
Genesis at a Glance
- Own the forge. We use Nix to define everything from the application stack to the forge OS image so the project can build and host itself on Hetzner (or any sovereign compute with dispatchable runners).
- Treat infrastructure as part of the artifact. Secrets, DNS, TLS, runners, and cron-based automation live in-repo so the forge can bootstrap, repair, and extend itself.
- Grow via agents, not commits alone. Scheduled jobs can spawn agents that open PRs, review each other’s work, and keep the system coherent without depending on centralized SaaS for CI/CD.
- Capture context for future models. Decisions, prompts, and architecture notes must live beside the code so the next generation of agents (and humans) can read them.
If you want the full stream-of-consciousness origin story, start with genesis.m4a (22 minutes) or the generated captions in genesis.srt.
Mission
- Deliver a production-quality, cross-platform password manager written in Swift, with first-class Apple, Web, and backend experiences.
- Maintain a self-hosted forge that can provision its own infrastructure, secrets, and runners via Nix, Hetzner, and Cloudflare DNS automation.
- Iterate safely by letting autonomous agents do the rote work while humans (or higher-level agents) set direction through the key.store evolution process.
System Pillars
- Crystalline Artifact: The password manager plus every prompt, script, and policy required to rebuild it. Nothing critical should live outside the repository (or its declared state stores).
- Sovereign Kernel: A minimal pool of trusted machines that can bootstrap new services, rotate credentials, and recover after failure using only the contents of this repo.
- Autonomous Evolution: Cron jobs and runners schedule agents that implement and review key.store evolution proposals, ensuring growth is intentional rather than chaotic.
Repository Tour
API/— Rust services and workers that back the product experience.Apple/— Native Swift code, likely the home of the flagship client.Web/— Web front-end assets and tooling.nixos/— Hosts, modules, and images used to spin up the forge and related services.Packages/&Scripts/— Shared tooling, Swift packages, agent helpers, and secret-management scripts.Makefile— Shortcuts fornix build,nix develop, and agenix-backed secret handling.
Bootstrapping the Stalwart directory
Stalwart expects a SQL directory with accounts, emails, and group_members tables (the schema in tests/src/directory/mod.rs mirrors what we use). Two helper scripts keep those tables aligned with the constitution:
# emit bootstrap.sql based on contributors.nix
python Scripts/generate-stalwart-sql.py > bootstrap.sql
# or stream it straight into psql (DATABASE_URL is optional if you source config/databases/stalwart-socket.env)
nix develop .#tools --command Scripts/apply-stalwart-sql.sh bootstrap.sql
# shorthand: auto-generate SQL and run it
nix develop .#tools --command Scripts/apply-stalwart-sql.sh
apply-stalwart-sql.sh reads config/databases/stalwart-socket.env (or respects DATABASE_URL/STALWART_DATABASE_URL) and runs the SQL with psql -v ON_ERROR_STOP=1, so rerunning it is idempotent. The generator now reads each secrets/identity/<slug>-password.age, hashes it (SHA-512 crypt), and stores the result in accounts.secret, so Stalwart’s internal directory always mirrors the canonical password list without ever writing plaintext into SQL output (run it on a host whose Age identity is in forgeAutomation).
Bootstrapping Forgejo accounts
Forgejo uses the same identity hierarchy for admin scope (governance), CI/service accounts (forgeAutomation), etc. The companion scripts follow the same pattern:
# review the generated user/email upserts
python Scripts/generate-forgejo-sql.py > forgejo.sql
# or stream directly (DATABASE_URL/forge secret is auto-resolved)
nix develop .#tools --command Scripts/apply-forgejo-sql.sh forgejo.sql
# shorthand auto-generate + apply
nix develop .#tools --command Scripts/apply-forgejo-sql.sh
The SQL upserts "user" rows for every contributor (governance identities become admins) and seeds the email_address table so Forgejo trusts their commit addresses. SSH keys still live in config/git-identities/ and are managed via Scripts/git-identity.sh per KSE-0001.
Getting Started
# drop into the reproducible dev shell
nix develop
# list or edit encrypted secrets (requires access)
make secrets-list
make secret name=cloudflare/api-token
# build everything described by flake.nix
nix build
Agents typically execute the same flows inside runners; humans can follow the steps above to reproduce their environment locally.
Commit Signing
All commits must be SSH-signed per KSE-0001. Use Scripts/git-identity.sh list to see the available identities, Scripts/git-identity.sh use <identity> (for example, agent) to configure your local git settings, and Scripts/git-identity.sh generate <identity> if you are onboarding a new signer. Public keys live in config/git-identities/, encrypted private keys now live under secrets/identity/<identity>-ssh.age, and .git_allowed_signers is regenerated by Scripts/git-identity.sh refresh. For OpenPGP/WKD publishing of identity@key.store addresses, follow docs/pgp-wkd.md and the helper script Scripts/wkd-publish.sh; the .well-known payload ships as the nix build .#wkd derivation and is bundled into the static web assets served by the API frontend.
The canonical roster (with scopes, hardware key notes, and Age recipients) lives in contributors.nix; run make contributors after editing it so CONTRIBUTORS.md and downstream tooling stay in sync.
Run Scripts/generate-allowed-signers.sh whenever you add/remove identities; review the resulting .git_allowed_signers diff before committing so the signer roster always matches config/git-identities/*.pub and the WKD tree.
Scripts/git-identity.sh generate --scope <tier> <identity> now writes three assets: the SSH key (secrets/identity/<identity>-ssh.age), an Age-encrypted OpenPGP backup (secrets/identity/<identity>-openpgp.age via Scripts/export-openpgp-secret.sh), and an encrypted SMTP password (secrets/forwardemail/<identity>-smtp.age via Scripts/forwardemail-alias.sh). Use Scripts/export-openpgp-secret.sh and Scripts/forwardemail-alias.sh manually whenever you rotate subkeys so the bundles stay current.
Universal plaintext login/password pairs (used by Stalwart, Forgejo OIDC bootstrap, and Plane) live in secrets/identity/<identity>-password.age. Generate or rotate them with make identity-passwords (optionally slug=<identity> or ROTATE=1); the helper script shells out to openssl rand -base64 32 so every identity gets a strong random secret without manual copy/paste.
See services/mail/stalwart-auth.md for the Stalwart-side OIDC runbook (client registration script, secret layout, and Forgejo wiring details).
Governance & Evolution
key.store uses a lightweight process inspired by Swift Evolution to capture architectural intent, major feature work, and agent-safe instructions. Every substantive change should be anchored by a proposal (KSE-XXXX) described in evolution/README.md and must cite the sections of the constitution it advances or depends on. Proposals live in evolution/proposals/ and act as durable context for future contributors.
Resources
- key.store constitution — binding statement of intent for humans and agents.
- Android Google Play upload runbook — upload-key export flow (
pepk.jar+ Play encryption key). - genesis.m4a — the original recording.
- genesis.txt — automated transcript (small.en Whisper model).
- genesis.srt — time-coded captions for quick scanning.
- forgejo/app.ini — hardened Forgejo defaults (signed-commit enforcement, branch protections) while keeping repos public.
When you update any of these resources (for example, regenerating the transcript with a newer model), note the change in the commit message so downstream agents know which context to trust.