docs(nip-fi): document the runtime configuration contract

- CORPORATE_IDENTITY.md: document BUZZ_NIP_FI_V1_CONFIG_JSON (Off /
  DenyProtected / Enforce), the complete runtime document with its field
  bounds, JWKS refresh limits, the 120-second status renewal bound, the
  removed legacy identity-provider variables that now fail startup, and
  the delegation default and enablement rules
- .env.example: replace the placeholder identity section with the
  commented document example and the legacy-variable removal note
- NIP_FI_DEPLOYMENT.md / NIP_FI_RUNTIME_OPERATIONS.md: document the
  single configuration input consistently and map the install-without-
  discovery step to the operating modes
- deploy READMEs: pgcrypto requirement for managed PostgreSQL, identity
  configuration pass-through with secret-handling guidance, and
  audit-capacity sizing guidance

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Cea Stapleton Cordasco <261786559+cea@users.noreply.github.com>
This commit is contained in:
Cea Stapleton Cordasco
2026-08-11 18:01:43 -05:00
parent 19b19b2e36
commit aa1bf732a9
6 changed files with 180 additions and 41 deletions

View File

@@ -54,12 +54,25 @@ RELAY_URL=ws://localhost:3000
# -----------------------------------------------------------------------------
# Federated identity (NIP-FI)
# -----------------------------------------------------------------------------
# This revision contains contract documentation only. It defines no supported
# NIP-FI runtime environment variables and does not activate enforcement.
# Review-only policy shape: docs/examples/nip-fi-stock-domain.json.example
# Do not convert that example into environment variables or trust a legacy
# corporate identity header. A later implementation release must document its
# exact adapter/configuration surface and matching behavioral evidence.
# Provider-free protected authorization is configured only through one JSON
# document. If BUZZ_NIP_FI_V1_CONFIG_JSON is absent, the runtime is Off. To
# deny every protected route during an emergency, use:
# BUZZ_NIP_FI_V1_CONFIG_JSON={"deny_protected":true}
#
# Full Enforce mode requires every RuntimeDocument field shown below. Replace
# the example endpoints and transport secret before enabling it. Delegation is
# disabled unless the document explicitly enables it with a non-empty closed
# capability list and a bounded maximum_seconds value.
# BUZZ_NIP_FI_V1_CONFIG_JSON={"issuer":"https://issuer.example","audience":"buzz-relay","subject_claim":"sub","event_author_claim":"nostr_pubkey","clock_skew_seconds":30,"maximum_token_lifetime_seconds":3600,"jwks":{"jwks_uri":"https://issuer.example/.well-known/jwks.json"},"lease":{"maximum_seconds":300},"policy_revision":1,"audit":{"max_events_per_domain":1000000,"max_bytes_per_domain":4294967296,"max_envelope_bytes":65536},"client_status_admission":{"max_presentations_per_domain":1000000,"max_presentations_per_actor":10000,"max_presentations_per_peer":10000},"transport":{"kind":"trusted_proxy_hmac_v2","active_secrets_base64url":["replace-with-base64url-secret"],"maximum_provenance_age_seconds":60,"future_skew_seconds":5},"enrollment":{"kind":"canonical_admission"},"restore":{"kind":"operation_manifest"},"delegation":{"enabled":false}}
#
# The complete document contract, field bounds, and activation gates are in
# docs/CORPORATE_IDENTITY.md and docs/NIP_FI_DEPLOYMENT.md. Configuring
# Enforce is not conformance evidence.
#
# Former identity-provider environment variables
# (BUZZ_REQUIRE_CORPORATE_IDENTITY and every BUZZ_CORPORATE_IDENTITY_* name)
# are removed. Setting any of them is a hard startup error; they are not
# aliases for this document.
# -----------------------------------------------------------------------------
# Git (NIP-34 bare repositories)

View File

@@ -52,6 +52,12 @@ See:
The chart fails at `helm install` / `helm template` time with a clear message if any of these are missing or malformed (see `templates/_validate.tpl`).
When `externalPostgresql.url` is used, the database must permit the `pgcrypto`
extension (schema bootstrap runs `CREATE EXTENSION IF NOT EXISTS pgcrypto`).
Most managed PostgreSQL offerings allow it, but the role applying migrations
needs the privilege to create it, or an administrator can pre-create the
extension.
## HA (production)
`replicaCount > 1` hard-requires Redis:
@@ -80,16 +86,21 @@ Save these. Losing any of them is data loss. See NOTES.txt printed by `helm inst
## NIP-FI readiness
This chart does not expose a NIP-FI runtime adapter, policy schema, trusted-edge
topology, secret keys, or conformance runner. Do not advertise or enforce
NIP-FI from this chart, and do not use an ingress identity header or
provider-specific sidecar as a fallback authority.
This chart does not provision a NIP-FI trusted-edge topology, issuer
integration, secret keys, or conformance runner. The relay's identity
configuration document (`BUZZ_NIP_FI_V1_CONFIG_JSON`, see the
[identity configuration contract](../../../docs/CORPORATE_IDENTITY.md)) can be
supplied like any other relay environment variable — keep the whole document
in `secrets.existingSecret` rather than values, because its
`transport.active_secrets_base64url` entries are live secret material. Do not
advertise or enforce NIP-FI from this chart, and do not use an ingress
identity header or provider-specific sidecar as a fallback authority.
A later chart release must pin an implementation with an exact adapter and
configuration version, keep policy separate from secret values, isolate
verifier ingress for `trusted-proxy-hmac-v1`, include every fail-closed
dependency in readiness, and link an immutable exact-head behavioral report.
A rendered chart and healthy pod do not prove those behaviors. See the
An activating deployment must pin an exact image, keep policy separate from
secret values, isolate verifier ingress for `trusted-proxy-hmac-v1`, include
every fail-closed dependency in readiness, and link an immutable exact-head
behavioral report. A rendered chart and healthy pod do not prove those
behaviors. See the
[provider-neutral deployment guide](../../../docs/NIP_FI_DEPLOYMENT.md) and
[runtime operations guide](../../../docs/NIP_FI_RUNTIME_OPERATIONS.md).

View File

@@ -36,6 +36,18 @@ keypair.
`buzz-admin migrate` before starting the relay when bootstrapping a fresh
database. Auto-migration requires an image that includes embedded SQLx
migrations.
- PostgreSQL must allow the `pgcrypto` extension — schema bootstrap and
migrations run `CREATE EXTENSION IF NOT EXISTS pgcrypto` (used for
`gen_random_uuid()` and digest hashing). On managed PostgreSQL, ensure the
extension is permitted for the migration role or pre-create it as an
administrator.
- Relay-verified identity (optional, off by default) is configured with
`BUZZ_NIP_FI_V1_CONFIG_JSON` (see the
[identity configuration contract](../../docs/CORPORATE_IDENTITY.md)). Its
`audit` bounds are a one-way lifetime budget per community domain — size
`max_events_per_domain` from expected identities × lifecycle operations with
generous headroom and monitor consumption, because exhaustion fails closed
and denies authorization-affecting operations rather than dropping evidence.
- The stack uses Postgres, Redis, MinIO, and a git data volume because
those are real Buzz dependencies today. Minimal mode can simplify this later.
@@ -43,16 +55,19 @@ Run `./run.sh backup-hint` for the backup checklist.
## NIP-FI readiness
This Compose bundle does not wire a NIP-FI runtime adapter, policy schema,
trusted edge, or conformance runner. Do not advertise or enforce NIP-FI from
this bundle, and do not add a provider-specific sidecar or unsigned corporate
identity header as a substitute.
This Compose bundle does not provision a NIP-FI trusted edge, issuer
integration, or conformance runner. The relay's identity configuration
document (`BUZZ_NIP_FI_V1_CONFIG_JSON`, see the
[identity configuration contract](../../docs/CORPORATE_IDENTITY.md)) passes
through like any other relay environment variable, but do not advertise or
enforce NIP-FI from this bundle, and do not add a provider-specific sidecar
or unsigned corporate identity header as a substitute.
A later implementation release must pin an exact image, document its supported
configuration and adapter version, isolate verifier ingress when
`trusted-proxy-hmac-v1` is enabled, deliver HMAC keys through a secret store,
and pass the complete exact-head behavioral matrix before activation. A valid
Compose render or healthy relay does not close those gates. See the
An activating deployment must pin an exact image, isolate verifier ingress
when `trusted-proxy-hmac-v1` is enabled, deliver HMAC secrets through a
secret store rather than `.env`, and pass the complete exact-head behavioral
matrix before activation. A valid Compose render or healthy relay does not
close those gates. See the
[provider-neutral deployment guide](../../docs/NIP_FI_DEPLOYMENT.md) and
[runtime operations guide](../../docs/NIP_FI_RUNTIME_OPERATIONS.md).

View File

@@ -2,22 +2,120 @@
Historical corporate identity approaches based on provider-specific middleware, unsigned forwarded headers, or a parallel authorization authority are retired guidance. Buzz's provider-neutral contract is [NIP-FI](nips/NIP-FI.md).
## Current status
## Runtime configuration
This documentation revision does not include a NIP-FI runtime adapter, activate identity enforcement, or establish conformance. Do not deploy a legacy identity sidecar or trust an identity header as a temporary substitute. A later exact-head implementation and deployment must pass the [behavioral evidence matrix](nips/NIP-FI-CONFORMANCE.md) before discovery or enforcement is enabled.
The relay's protected authorization runtime is configured only with the
`BUZZ_NIP_FI_V1_CONFIG_JSON` environment variable. The former
identity-provider variables (`BUZZ_REQUIRE_CORPORATE_IDENTITY` and every
`BUZZ_CORPORATE_IDENTITY_*` name) are removed: setting any of them fails
startup instead of weakening policy, and none of them is an alias for the
document below.
### Delegation availability
Configuring the runtime is not conformance. A deployment must pass the
[behavioral evidence matrix](nips/NIP-FI-CONFORMANCE.md) at its exact
deployed revision before NIP-FI discovery or enforcement is advertised, and
operators must verify the effective configuration in their deployment;
public wording alone is not activation or conformance evidence.
### Operating modes
- **Off:** leave `BUZZ_NIP_FI_V1_CONFIG_JSON` unset. Protected composition is
not installed and existing unprotected behavior remains available.
- **DenyProtected:** set the document to `{"deny_protected":true}`. Every
protected route is denied before its handler runs. `deny_protected` takes
precedence over every other field in the document.
- **Enforce:** provide the complete document below. Missing, unknown, empty, or
invalid fields fail startup.
```json
{
"issuer": "https://issuer.example",
"audience": "buzz-relay",
"subject_claim": "sub",
"event_author_claim": "nostr_pubkey",
"clock_skew_seconds": 30,
"maximum_token_lifetime_seconds": 3600,
"jwks": {
"jwks_uri": "https://issuer.example/.well-known/jwks.json"
},
"lease": { "maximum_seconds": 300 },
"policy_revision": 1,
"audit": {
"max_events_per_domain": 1000000,
"max_bytes_per_domain": 4294967296,
"max_envelope_bytes": 65536
},
"client_status_admission": {
"max_presentations_per_domain": 1000000,
"max_presentations_per_actor": 10000,
"max_presentations_per_peer": 10000
},
"transport": {
"kind": "trusted_proxy_hmac_v2",
"active_secrets_base64url": ["replace-with-base64url-secret"],
"maximum_provenance_age_seconds": 60,
"future_skew_seconds": 5
},
"enrollment": { "kind": "canonical_admission" },
"restore": { "kind": "operation_manifest" },
"delegation": { "enabled": false }
}
```
### Document rules and bounds
The document rejects unknown fields. In Enforce mode:
- `issuer` and `audience` are required non-empty strings of at most 2048
characters each.
- `subject_claim` defaults to `sub`. It and the optional `event_author_claim`
are limited to 128 characters.
- `clock_skew_seconds` defaults to `0` and is at most 300.
- `maximum_token_lifetime_seconds` is required, positive, and at most 86400.
- `jwks` accepts exactly one HTTPS `jwks_uri` or `discovery_uri`; credentials,
fragments, redirects, and private-network targets are rejected.
- `lease.maximum_seconds` is required, positive, and at most 3600.
- `policy_revision` is required and positive.
- `audit` sets the immutable authorization-evidence capacity
(`max_events_per_domain`, `max_bytes_per_domain`, `max_envelope_bytes`).
There is no online prune, export, reset, or acknowledgement workflow — size
the budget for the installation's lifetime with generous headroom, because
exhaustion denies further authorization-affecting operations instead of
dropping evidence.
- `client_status_admission` limits are positive;
`max_presentations_per_domain` cannot exceed `audit.max_events_per_domain`,
and the per-actor and per-peer limits cannot exceed the per-domain limit.
- `transport`, `enrollment`, and `restore` are required non-empty objects
consumed by the matching runtime adapters. Production ingress requires the
exact `trusted_proxy_hmac_v2` transport configuration shown above; the
trusted-proxy provenance verifier is constructed at startup, before
listeners open.
The `jwks` refresh policy is validated at construction: a fetched document
cannot exceed 4 MiB, a snapshot cannot stay fresh longer than 24 hours, every
refresh bound is finite and nonzero, and an accepted key set contains between
1 and 128 keys. Production uses tighter bounds. Key refreshes are
single-flight and stale verification fails closed. Current-status
presentation renews within 120 seconds, so active connections observe
authoritative policy changes within that polling bound.
### Delegation
Delegation is disabled by default. Omitting the `delegation` object or setting
`{"enabled": false}` disables it, and a disabled delegation object must not
carry capabilities or a lifetime. Enabling it requires `enabled: true`, a
non-empty unique `capabilities` list drawn from the closed route-capability
set, and a positive `maximum_seconds` of at most 3600 that does not exceed
`lease.maximum_seconds`. Delegated authority is always capability-scoped —
never transport-wide — and the relay's NIP-11 information document does not
advertise delegation.
Corporate-identity delegation is currently unsupported. The public production
path does not implement complete delegated issuance, owner-bound resolution,
expiry, invalidation, reconnect, or protected-transport behavior. Operators
must keep delegation disabled, and discovery must report it as false or omit
it. A legacy or downstream configuration flag does not add the missing
authority and must not be used to advertise support.
This documentation-only revision does not change runtime code or configuration
defaults. Operators must verify the effective setting in their deployment;
public wording alone is not activation or conformance evidence. See the
it. Enabling the configuration shape does not add the missing authority and
must not be used to advertise support. See the
[integration guide's availability boundary](NIP_FI_INTEGRATION.md#delegation-availability)
for the implementation and evidence requirements.

View File

@@ -1,12 +1,14 @@
# NIP-FI stock deployment
This guide describes a provider-neutral stock deployment for the normative [NIP-FI contract](nips/NIP-FI.md). It does not define runtime configuration keys or activate support.
This guide describes a provider-neutral stock deployment for the normative [NIP-FI contract](nips/NIP-FI.md). It does not by itself activate support.
## Current status
## Runtime configuration
This documentation revision ships no NIP-FI runtime adapter, configuration schema, image capability, or conformance report. The current Compose and Helm bundles must not advertise or enforce NIP-FI. A later implementation release must document its exact adapter and configuration surface and pass the [behavioral evidence matrix](nips/NIP-FI-CONFORMANCE.md) at the deployed revision before activation.
The relay accepts exactly one identity-configuration input: the `BUZZ_NIP_FI_V1_CONFIG_JSON` environment variable. Absent means Off, `{"deny_protected":true}` denies every protected route before its handler runs, and only the complete document enables Enforce mode. The document contract, field bounds, and startup rejection rules — including the removed legacy identity-provider variables, which fail startup when set — are documented in the [identity configuration contract](CORPORATE_IDENTITY.md).
The files under [`docs/examples`](examples/) are review templates. They are not accepted runtime schemas and contain no deployable secrets.
Configuring Enforce is not conformance. A deployment must not advertise or enforce NIP-FI until it passes the [behavioral evidence matrix](nips/NIP-FI-CONFORMANCE.md) at the deployed revision.
The files under [`docs/examples`](examples/) are review templates. They are not accepted runtime schemas — the only runtime input is the environment variable above — and they contain no deployable secrets.
## Stock topology
@@ -41,7 +43,7 @@ A source scan, config parse, rendered manifest, healthy process, or documentatio
Use one reviewed policy object per server-selected domain. The review-only [stock domain example](examples/nip-fi-stock-domain.json.example) records the required decisions without claiming a runtime schema.
At minimum, the later runtime schema must represent:
The runtime document and its fixed verifier semantics together represent:
- exact domain identity and trusted listener or route mapping;
- accepted issuer and audience values;
@@ -101,7 +103,7 @@ List every protected ingress and its current authorization path. Include WebSock
### 2. Install without discovery
Deploy the exact implementation artifact with NIP-FI discovery and enforcement off. Load reviewed policy and secret references. Validate issuer connectivity, JWKS authenticity, state migrations, backup, observability redaction, and route inventory without creating production bindings.
Deploy the exact implementation artifact with NIP-FI discovery and enforcement off — leave `BUZZ_NIP_FI_V1_CONFIG_JSON` unset, or set `{"deny_protected":true}` where protected routes must already deny. Load reviewed policy and secret references. Validate issuer connectivity, JWKS authenticity, state migrations, backup, observability redaction, and route inventory without creating production bindings.
### 3. Run isolated behavior

View File

@@ -2,9 +2,9 @@
This guide covers lifecycle, recovery, restore, and rollback for a conforming Buzz NIP-FI implementation. The normative [specification](nips/NIP-FI.md) and [formal model](nips/NIP-FI-MODEL.md) control when this guide differs.
## Current status
## Runtime configuration
This documentation revision supplies no runtime adapter or operator command. Command names and request schemas must come from the later exact-head implementation stack. The [recovery-plan example](examples/nip-fi-recovery-plan.json.example) is a review template, not a runtime request.
The runtime's sole identity-configuration input is `BUZZ_NIP_FI_V1_CONFIG_JSON`: absent is Off, `{"deny_protected":true}` denies every protected route, and the complete document enables Enforce. Field bounds and the removed legacy identity-provider variables — which fail startup when set — are documented in the [identity configuration contract](CORPORATE_IDENTITY.md). Operator lifecycle command names and request schemas come from the implementation's own operator tooling; the [recovery-plan example](examples/nip-fi-recovery-plan.json.example) is a review template, not a runtime request.
Do not simulate an operator transition with direct database edits. Every authority change uses a separately authorized, audited transition with fresh target-key proof when a new key is introduced.