openvibers/openvibe.contracts Commits

AGENTS.md: the context an agent starts from (#459)

OP OpenVibers committed 1 days ago · d06748a6b2 · 2 files, +147 −0

Changes

ddiff --git a/AGENTS.md b/AGENTS.md
nnew file mode 100644
iindex 00000000..9f71fa59
---- /dev/null
++++ b/AGENTS.md
@@@ -0,0 +1,146 @@
++# AGENTS.md — OpenVibe.Contracts
++
++## Project overview
++
++The machine-readable contract layer of the whole OpenVibe network: schemas, ids, the HTTP/error
++envelope, capability checks, service/namespace/topic manifests, the staff capability map and the
++compatibility aliases. A **library**, not a service: no runtime, no database, no ports, no deploy.
++
++- Package `openvibe-contracts`, `main` [index.js](index.js), version in [package.json](package.json)
++ (currently `0.410.0`, released as the git tag `v0.410.0`).
++- Every service pins a release tarball and verifies service/app tokens with `serviceAuth` in
++ production; the service repositories run `openvibe-contracts-check` and the pin-drift check in CI.
++- Scale at this release: 1261 schemas in [contracts/catalog.json](contracts/catalog.json), 67 service
++ manifests, 523 capability manifests, 14 namespace manifests and the staff map.
++
++## What it owns
++
++- Contract IDs, semantic versions, owners, visibility and deprecation state.
++- `SubjectRef` (`user|guest|service|app|mod|system` + stable id) and the legacy identity map shape.
++- The request/error envelope: `traceparent`, `X-OpenVibe-Request-Id`, `Idempotency-Key`, RFC 9457
++ problem details, resource `revision`/ETag.
++- The capability contract (id, owner, input/output schema, permissions, resource constraints, quota
++ class, events), namespace and topic manifests, and compatibility aliases/deprecations.
++- Service manifests (what each service runs, its routes and events) and the staff capability map.
++- Generated JSON Schema, TypeScript and OpenAPI artifacts, and the estate map.
++
++Not owned: any runtime behaviour, a database, identity issuance (Network), or the implementation of a
++capability (the owning service).
++
++## How a service consumes it
++
++```js
++const contracts = require('openvibe-contracts');
++contracts.validate('identity.subject-ref@1', { type: 'user', id: 'usr_…' }); // { valid, errors }
++contracts.ids.newId('user'); // usr_<ULID>
++contracts.http.problem(403, 'capability.denied'); // RFC 9457 body
++contracts.capabilities.check(claims, 'media.object.read', { namespace: 'live' });
++contracts.resource.parse('ovrn:media:prj_…:object/med_…');
++```
++
++`serviceAuth.requireCapability(...)` judges a request that presents a Bearer token **on that token
++alone**; a bad token is never rescued by a legacy header. It verifies RS256, issuer, audience and
++expiry, and grants a capability only by exact id or a `family.*` grant. Production services must use it.
++
++## Repository map
++
++- **Public API:** [index.js](index.js) — `catalog`, `resolve`, `validate`, `assertValid`, `schema`,
++ `ids`, `http`, `capabilities`, `services`, `products`, `serviceAuth`, `modules`, `tools`, `zones`,
++ `usage`, `resources`, `staff`, `openapi`.
++- **Implementation:** [lib/](lib/) — `registry.js` (catalog loading/resolution), `ids.js`, `http.js`,
++ `capabilities.js`, `services.js`, `products.js`, `service-auth.js`, `modules.js`, `tools.js`,
++ `zones.js`, `usage.js`, `resources.js`, `staff.js`, `openapi.js`, `money-reasons.js`.
++- **Schemas:** [contracts/](contracts/) grouped by area (`actor/`, `agent/`, `ai/`, `bench/`, `billing/`,
++ `blog/`, …), indexed by [contracts/catalog.json](contracts/catalog.json).
++- **Fixtures:** [fixtures/](fixtures/) — each contract has `valid/` and `invalid/` examples.
++- **Manifests:** [manifests/](manifests/) — services, capabilities, namespaces, topics, policy
++ (`manifests/policy/staff-roles.json` is the one source for staff gates).
++- **Compatibility:** [compatibility/](compatibility/) — `aliases.json`, `deprecations.json`,
++ `corrections.json`, `capability-schema-gaps.json`, `compat.js`.
++- **Generated:** [generated/](generated/) — `json-schema/`, `typescript/`, `openapi/`; never hand-edit.
++- **Scripts:** [scripts/generate.js](scripts/generate.js), [scripts/compat.js](scripts/compat.js),
++ [scripts/estate.js](scripts/estate.js), [scripts/docs-currency.js](scripts/docs-currency.js).
++- **Service check:** [bin/check-service.js](bin/check-service.js) → `openvibe-contracts-check`.
++- **Governance/ADRs:** [governance/](governance/), [docs/adr/](docs/adr/), [docs/](docs/).
++
++## Commands
++
++```bash
++npm ci
++npm test # every check in test/ (schemas, fixtures, manifests, compatibility, docs)
++npm run generate # regenerate generated/json-schema, generated/typescript, generated/openapi
++npm run estate # regenerate docs/ESTATE.md and manifests/repositories/
++node scripts/estate.js --check # fail on drift against the estate checkouts
++node scripts/docs-currency.js <root> # check every checkout's README/STATUS against its code
++node --check <file.js>
++```
++
++The repository is consumed, never started; there is nothing to `npm start`.
++
++## Adding or changing a contract (the release round)
++
++1. Add the schema under the owning area in [contracts/](contracts/) with its `$id`, version, owner and
++ `@1`/next-version id, and add it to [contracts/catalog.json](contracts/catalog.json).
++2. Add [fixtures/&lt;id&gt;/valid/](fixtures/) and `invalid/` examples; the suite validates both.
++3. Add or update the capability/namespace/service manifest if the change introduces a capability.
++4. `npm run generate` and commit the regenerated files together with the schema (never by hand).
++5. Raise `package.json`'s version above main's newest version, add the CHANGELOG entry, commit and tag
++ `vX.Y.Z`. `scripts/compat.js` bases its comparison on `git describe HEAD^`, so a release needs its
++ **own commit after the merge** — do not tag a merge commit that main has moved past.
++6. Consumers bump their pinned tarball tag; a new capability id must ship here **before** the service
++ that uses it, or the service refuses every caller (unknown ids fail closed).
++
++## Versioning and compatibility
++
++- Schemas and capabilities are semver'd: additive fields/ids are a minor, a breaking shape is a new
++ `@2` contract (never an edit to `@1`), with a migration path and a deprecation entry.
++- [compatibility/](compatibility/) records aliases, deprecations and corrections; the suite checks them
++ against the catalog.
++- A released tag is immutable: do not rewrite or re-tag it, and do not edit a released schema in place.
++
++## Security
++
++- `serviceAuth` verifies the token alone (no legacy header rescue), RS256, issuer, audience and expiry;
++ capabilities are exact-id or `family.*`.
++- The staff capability map ([manifests/policy/staff-roles.json](manifests/policy/staff-roles.json)) is
++ the single source for staff gates; do not duplicate it in a service.
++- Schemas carry no secrets and no personal data; fixtures use fake values, and gitleaks scans history
++ in CI. Dependencies are `ajv` and `ajv-formats` only — adding one needs a reason.
++
++## Tests
++
++`npm test` runs [test/run.js](test/run.js), which loads every `test/*.test.js` check (the run aggregates
++sub-scripts for schema validation, fixtures, capability schemas, manifests, compatibility, changelog
++history, docs currency, estate). It is plain Node `assert`, no framework. A check that cannot run
++prints `<label>: skipped (<why>)`; `--strict` (or `OV_TEST_STRICT=1`) makes a skip fail. `npm run
++estate` and `node scripts/docs-currency.js <root>` are separate drift checks used in CI. `ov test` runs
++the harness's shard.
++
++## Pitfalls
++
++- **Never hand-edit [generated/](generated/).** Run `npm run generate`; a generated diff you cannot
++ reproduce is a bug.
++- **Every schema needs fixtures and a catalog entry.** A schema outside `catalog.json` does not exist to
++ consumers; a fixture-less schema is untested.
++- **Do not reuse or renumber an id.** Consumers key on the exact id and version; a change is a new
++ version, a deprecation and an alias where needed.
++- **Do not tag before the release commit.** `scripts/compat.js` looks at `HEAD^`; tag after the version
++ commit, and bump in the same commit as the generated output.
++- **A capability must be released before a service guards a route with it**; an unknown id is refused,
++ never allowed.
++- **`docs/ESTATE.md` and `manifests/repositories/` are generated from the estate checkouts**; run
++ `npm run estate` and commit the result, or `--check` fails.
++- **`scripts/docs-currency.js` trusts the checkouts it is given**; run it with the estate root, not a
++ single repository, when checking a pin round.
++- **`serviceAuth` is deliberately strict.** Do not add a compatibility shim that accepts an unsigned or
++ wrong-audience token to make an old caller work.
++
++## Documentation
++
++- [README.md](README.md) — the API, contract groups, versioning and purpose.
++- [docs/ESTATE.md](docs/ESTATE.md) — the generated estate map.
++- [docs/adr/](docs/adr/) — every architecture decision (ADR-012 money, ADR-019 publishing, ADR-035
++ data, ADR-043 Bot, ADR-044 Actor, ADR-050 Codes, ADR-057 Connect, …).
++- [docs/sharing.md](docs/sharing.md), [docs/locker.md](docs/locker.md),
++ [docs/space-problem-codes.md](docs/space-problem-codes.md).
++- [governance/](governance/) — contract governance process.
ddiff --git a/CLAUDE.md b/CLAUDE.md
nnew file mode 100644
iindex 00000000..43c994c2
---- /dev/null
++++ b/CLAUDE.md
@@@ -0,0 +1 @@