m5/org/openalice-vault

openalice-vault

Features
2
Status
·unknown
Last activity
1mo ago
Branch
mvp

Architecture rating

B1mo ago
securityA-

JWT-gated identity surface + per-owner rate-limit (600 RPM default); RLS+FORCE on all 5 tables with SET LOCAL app.owner_id (injection-safe set_config); 0600 Ed25519 keyfile with perm check + zeroize-on-drop KMS; AAD-bound XChaCha20 bundle seal AND AES-256-GCM DEK wrap (transplant-reject tested); BlobStore rejects path traversal (3 test vectors); prod-secret boot guard panics on shipped dev defaults; cargo-deny gates advisories+licenses+sources; security-headers + normalize_errors middleware; internal error detail never leaked to client.

data layerA-

5-table schema with FK constraints (vault_versions/dek_meta/consent_records → identities), CHECK constraints on subject_kind + status enums, UNIQUE (identity_id,version); RLS owner policies on all 5 tables with idempotent FORCE toggle helpers and NOSUPERUSER/NOBYPASSRLS prerequisite documented; owner_user_id denormalized onto every child (no JOIN for policy eval); crypto-shred = NULL wrapped_dek + shredded_at + zero-overwrite blob delete (GDPR erasure); versioned migrations (0001_init + 0002_audit_signed_at binding timestamp into signed surface); UUIDv7 PKs.

testingB

~63 tests (55 inline unit + 8 DB-gated acceptance): crypto paths deeply covered (seal/open roundtrip, AAD-transplant rejection at both DEK-wrap and bundle-seal layers, tampered ciphertext, wrong key, nonce uniqueness); audit hash-chain tested for valid/tampered-core/tampered-timestamp/removed/reordered/forged-key; acceptance tests cover full seal→verify→shred lifecycle, RLS cross-owner isolation (alice vs mallory), version chaining with parent_hash, revoke-without-erasure, mandate-gated instantiation; boot-guard + vault-mode unit tests. Gap: no HTTP-level handler integration tests (api/mod.rs handlers untested at the HTTP boundary), acceptance gated behind TEST_DATABASE_URL.

consistencyB-

Shares openalice-axum-common for CORS, rate-limit (TenantRateLimit), AuthUser/JwtVerifier, tracing init, HTTP metrics, security-headers, normalize_errors, shutdown, internal_client — mirrors openalice-tenants skeleton explicitly; consistent middleware layer ordering documented in router.rs; uniform {error:{code,message}} envelope; rustls-only posture (sqlx + reqwest); cargo-deny with org-standard config. Gaps: 85 missing docstrings, 7 god-module flags, duplicate error types (api::ApiError vs error::AppError both do status→JSON mapping).

observabilityB-

Prometheus /metrics endpoint with HTTP latency+count middleware (bounded cardinality via MatchedPath); /health returns 200/503 with dep status JSON (postgres: ok/down); structured tracing with env-filter + OTEL span export when OTEL_EXPORTER_OTLP_ENDPOINT set; W3C traceparent propagation (propagate_incoming); INFO-level request spans. Missing: no custom business metrics (seal/shred counts), health probe doesn't report crypto subsystem readiness, no separate readiness vs liveness probe.

reliabilityC+

Graceful shutdown via with_graceful_shutdown(shutdown_signal()); pool acquire_timeout 5s (4..20 conns); boot-guard pattern — absent signing key or master key degrades to 503 on identity endpoints while /health stays live; kill switch (off/on/shadow) for incident response; blob write-before-insert prevents dangling rows; SET LOCAL tx-scoped owner context never leaks across pooled connections; idempotent RLS toggle. Gaps: no retry/backoff on transient DB errors, no explicit request-level timeout, no idempotency keys on create/seal (client retry could duplicate).

docsC-

Excellent inline module docs (//! blocks on every module explaining purpose, security invariants, Alex §13 decisions, milestone scope); 2 @feature annotations (rate-limit, identity-custodian); migrations carry detailed schema/RLS design comments; cargo-deny thoroughly commented. Gaps: no README (Atlas readme_excerpt empty), no OpenAPI/Swagger spec, 85 missing function-level docstrings per inspector, only 2 registered features vs the full lifecycle surface, no architecture diagram.

source · auto-grader-2026-06-17

Code composition

tokei · loc
3.5kloc
  • Rust93.4%
  • TOML3.0%
  • SQL2.9%
  • Dockerfile0.7%
  • Rust93.4%· 3,309
  • TOML3.0%· 108
  • SQL2.9%· 102
  • Dockerfile0.7%· 24
Language% codecodecommentsblanksfiles
Rust93.4%3,30919937324
TOML3.0%10874122
SQL2.9%10269192
Dockerfile0.7%2420121
Markdown0.0%0115221

Telemetry ribbon · last 90 days

7 events
MAYJUNJUL2026-06-16 · lifecycle · first scan — repo indexed2026-06-16 · commit · new commit a902895 → 9e44b512026-06-16 · commit · new commit 9e44b51 → b9702ea2026-06-16 · commit · new commit b9702ea → c6c0b682026-06-16 · commit · new commit c6c0b68 → ec344d82026-06-17 · commit · new commit ec344d8 → e0373a62026-06-17 · commit · new commit e0373a6 → 1c35ab7NOW
commitmanifestlifecyclekind

vault/crate

1 feature
  • vault.crate.identity-custodian
    src/lib.rs:3
    Rust/Axum service (port 3992) that seals, versions, and crypto-shreds per-owner *identities* — NOT a generic secrets store. Each identity is a signed, content-addressed bundle (manifest + encrypted blob), wrapped by a per-identity Data Encryption Key (DEK) that itself is KEK-wrapped. Crypto shred = drop the wrapped DEK → the blob is permanently unreadable. Owner isolation is enforced by Postgres Row-Level Security keyed on `app.owner_id` (see [`db`]); the app role MUST be NOSUPERUSER NOBYPASSRLS for FORCE RLS to bite (applied at boot via `VAULT_RLS_ENFORCE`). M1.1 ships the COMPILING skeleton: HTTP wire surface (health + 501-stub identity routes), the owner-scoped DB/RLS plumbing, and the schema. The crypto / bundle / store / audit / consent / api modules are STUBS — Tycho implements them in M1.2+.

vault/middleware

1 feature
  • vault.middleware.rate-limit
    src/main.rs:3
    Per-owner token-bucket rate limiter on /v1/identities/* (default 600 req/min ≈ 10 RPS, overridable via VAULT_RATE_LIMIT_PER_MINUTE). Guards against a runaway agent loop abusing a single owner's bearer while staying invisible to normal interactive use. Provided by openalice-axum-common::rate_limit. default-rpm: 600 Routes are split into: * `/health` — Traefik liveness probe. * `/metrics` — Prometheus scrape. * `/v1/identities/*` — owner-facing identity lifecycle (create, seal, versions, export, crypto-shred). M1.1: 501 stubs (see `router`). The identity handlers (crypto/store/audit-backed) land in M1.2+; for now they stub-respond 501 so the wire surface + RLS scaffold ship first.