Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions contracts/identity-vault/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules/
.npm-cache/
probe.yaml
3 changes: 3 additions & 0 deletions contracts/identity-vault/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@fuzekeys:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}
always-auth=true
24 changes: 24 additions & 0 deletions contracts/identity-vault/.spectral.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
extends: ["spectral:oas"]
# Spectral ruleset for the Secrets-Broker contract.
# Base = the official OpenAPI (oas) rules; a few tightenings below for a
# security-sensitive vault API.
rules:
# Every operation must declare an operationId (generated-client method names).
operation-operationId: error
operation-operationId-unique: error
# Tags used by operations must be declared at the top level.
operation-tag-defined: error
# Operations must declare a success (2xx) response.
operation-success-response: error
# Info hygiene for a published contract.
info-contact: warn
info-description: error
# Servers should be defined.
oas3-api-servers: error
# Spectral 6.x + nimma crashes traversing some OpenAPI 3.1 schemas under these
# example/typed-enum rules ("Cannot read properties of null (reading 'enum')").
# Disabled so structural linting runs cleanly; schema validity is covered by
# the YAML parse + openapi-typescript generation succeeding.
typed-enum: off
oas3-valid-schema-example: off
oas3-valid-media-example: off
31 changes: 31 additions & 0 deletions contracts/identity-vault/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Changelog — Secrets-Broker contract

All notable changes to the Identity-Vault Secrets-Broker contract
(`openapi.yaml` + `mcp-tools.json`) are recorded here. The contract is the
fan-out gate; every change bumps `info.version` / `package.json` version
(semver) and ripples to all generated clients through the contract PR.

## [0.1.0] - 2026-06-26

Initial frozen contract — Phase 2 fan-out gate.

### Added
- OpenAPI 3.1 spec (`openapi.yaml`) for the Secrets-Broker REST API:
- Discovery (metadata only): `GET /identities`, `/identities/{id}/site-logins`,
`/identities/{id}/api-tokens`.
- Policy-gated secret access: `GET /identities/{id}/profile`,
`/site-logins/{site}`, `/site-logins/{site}/totp` (current code, never the seed),
`/cards/{cardId}` (HIGH -> 202), `/api-tokens/{service}` (HIGH -> 202).
- Write: `POST /identities/{id}/site-logins`.
- Approval workflow: `GET /approvals/{request_id}` (one-time short-TTL value),
`GET /approvals`, `POST /approvals/{request_id}/approve|deny`.
- Management CRUD-lite: organizations, organization members, identities, agents,
agent scopes, agent token rotation, and `GET /audit-log`.
- `components/schemas` for every design Section 5 entity + all request/response
bodies; sensitivity tiers (LOW/MEDIUM/HIGH) encoded; HIGH => approval.
- `agentBearer` security scheme (hashed agent token, owner + scope enforcement);
401/403/404/202 responses reflecting the security model.
- MCP tool contract (`mcp-tools.json`) for all 10 tools from design Section 6,
field-aligned with the REST schemas.
- Spectral ruleset (`.spectral.yaml`), `package.json` scripts (lint / mock /
gen:types), scoped `.npmrc`, and the generated TS types under `client/`.
59 changes: 59 additions & 0 deletions contracts/identity-vault/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Identity Vault — Secrets-Broker Contract (Phase 2, frozen gate)

This is the **frozen contract** for the FuzeKeys identity-vault Secrets-Broker. Backend, UI,
and tests are all built against it (see design
`docs/superpowers/specs/2026-06-24-identity-vault-mcp-design.md`). Changes ripple deliberately:
amend via PR, don't diverge silently.

## Files
| File | Purpose |
|------|---------|
| `openapi.yaml` | OpenAPI 3.1 REST contract (23 paths, 46 schemas) — the broker implements this |
| `mcp-tools.json` | MCP tool contract (10 tools) the agent-facing MCP server exposes |
| `.spectral.yaml` | Spectral lint ruleset for `openapi.yaml` |
| `package.json` | scripts: `lint`, `mock`, `gen:types` |
| `client/` | generated TS types (`gen:types` output; consumed by UI/tests) |

## MCP tool ↔ REST endpoint mapping
| MCP tool | REST endpoint | Tier |
|----------|---------------|------|
| `list_identities` | `GET /identities` | metadata |
| `list_site_logins` | `GET /identities/{id}/site-logins` | metadata |
| `list_api_tokens` | `GET /identities/{id}/api-tokens` | metadata |
| `get_identity_profile` | `GET /identities/{id}/profile` | LOW auto · SSN/passport → approval |
| `get_site_login` | `GET /identities/{id}/site-logins/{site}` | MEDIUM (auto in-scope) |
| `get_totp_code` | `GET /identities/{id}/site-logins/{site}/totp` | MEDIUM — returns the **current code, never the seed** |
| `get_card` | `GET /identities/{id}/cards/{cardId}` | HIGH → approval |
| `get_api_token` | `GET /identities/{id}/api-tokens/{service}` | HIGH → approval |
| `store_site_login` | `POST /identities/{id}/site-logins` | write (policy-gated, audited) |
| `check_approval` | `GET /approvals/{request_id}` | — |

## Sensitivity & approval semantics
- **LOW** (metadata, display name) and **MEDIUM** (site password, TOTP code) release automatically
*when in scope*, and are audited.
- **HIGH** (cards, API tokens, SSN/passport) return **HTTP 202** `{status:"approval_required",
request_id, expires_at}`. The agent polls `GET /approvals/{request_id}`; once a human approves
(in-app / Telegram / Slack / email), it returns a **one-time, short-TTL** value. Denied/expired
requests never release.

## Security model (encoded in the spec)
- Agent auth: **bearer token** (`securitySchemes`), bound to a user + scope.
- The broker's scope check is the tenant boundary (single Vaultwarden silo): `401` bad/missing
token, `403` out-of-scope / cross-tenant, `404` not found under the supplied owner, `202`
approval required. No endpoint returns a secret without passing policy + writing an audit record.

## Consuming the contract
```bash
cd contracts/identity-vault
npm install # spectral, prism, openapi-typescript (see package.json)
npm run lint # spectral lint openapi.yaml
npm run mock # prism mock server — UI/tests build against this, no backend needed
npm run gen:types # openapi-typescript -> client/types.ts (shared types for UI/tests)
```
The backend implements `openapi.yaml`; the independent test suite asserts against the **same**
spec, so contract drift becomes a failure.

## Status
**Frozen** as the Phase 2 fan-out gate. Phases 3–5 (vault infra, broker, approval UI) build
against this. Validated: `openapi.yaml` and `mcp-tools.json` parse; field names/types are
consistent between the REST schemas and the MCP tool I/O.
Loading
Loading