openvibers/openvibe.codes Commits
README and STATUS.json are current (roadmap WS-U task 3): the grants section opens with the two capabilities Codes implements and every grant it uses elsewhere (its principal, the person's token, the app's token, Network export tokens); the threat notes are now a Security section that points to SECURITY.md; Deploy says production deploys with sudo ovhost deploy codes (unit, port, env file, state, vhost, rollback and its one blocker) and keeps the first-install steps; Depends on names the current pins (contracts v0.53.0, sdk v0.12.0, shared v1.22.0). STATUS.json gains contracts and features, lists the per-project usage page (no longer under notYet), drops a stale release sha and is updated 2026-09-28.
Changes
@@@ -47,18 +47,28 @@ Everything is server-rendered and usable without JavaScript. The only scripts of- **OpenVibe.Network** — SSO (OAuth client `codes`, PKCE S256), JWKS, `/api/v1/projects` (called server-side with the person's Network access token), the registry (`/api/v1/registry/services`, `/.well-known/openvibe`), client-credentials tokens (Codes' own for the events relay; the app's own in playgrounds).- **OpenVibe.Events** — the outbox relay publishes `codes.app.*` with Codes' service token (`events.event.publish`); the Events playground calls it with the app's token (`events.app.publish`); the project archive pulls the project's app events with a Network export token (`events.app.read`).- **OpenVibe.Media** — the Media playground uploads with the app's token into the project's namespace; the project archive lists the project's objects, namespaces and download URLs with a Network export token (`media.object.list`, `media.object.read`).--- **openvibe-contracts** v0.33.0, **openvibe-sdk v0.5.0**, **openvibe-shared v1.5.1** (pinned tag tarballs; the docs show the tag and the package version, and say so when they differ).++- **openvibe-contracts** v0.53.0, **openvibe-sdk v0.12.0**, **openvibe-shared v1.22.0** (pinned tag tarballs; the docs show the tag and the package version, and say so when they differ).No path in Codes sends or accepts a shared loopback key (tested by grep and at runtime).## Grants and registration the lead must add++Implemented here (the service manifest's `capabilities`): `codes.release.read` (public release reads;++no token needed, a presented token must hold it) and `codes.release.manage` (release management by an++app with its own token), both guarded with openvibe-contracts `requireCapability`.++++Called elsewhere: as the service principal `codes`, `events.event.publish` at Events (the outbox relay);++as the signed-in person, with their own Network token, Network's `/api/v1/projects`; as the app, with++its own token, `media.object.upload` (Media) and `events.app.publish` (Events) in the playgrounds; and,++for the project archive, Network's read-only export tokens holding `events.app.read`,++`media.object.list` and `media.object.read`.++In Network (`server/identity/principals.js` / `server/db/database.js`, as for coupons and host):- OAuth client `codes`, name `OpenVibe.Codes`, redirect URI `https://openvibe.codes/auth/callback`.- Service grant `['codes', 'events.event.publish', 'openvibe.events', []]` (the outbox relay).--The Codes service manifest, `codes.release.manage|read` and `codes.app-manifest@1` are released in openvibe-contracts (tag v0.27.0; this repository pins v0.33.0); the CI contracts check is blocking.++The Codes service manifest, `codes.release.manage|read` and `codes.app-manifest@1` are released in openvibe-contracts (tag v0.27.0; this repository pins v0.53.0); the CI contracts check is blocking.For the playgrounds to succeed end to end (not Codes' code; configuration elsewhere): Network `DEV_SANDBOX_AUDIENCES` including `openvibe.media` and `openvibe.events`, a staff-set allowance containing `media.object.upload` and `events.app.publish` for the project, a Media tenant keyed by the project id, and OpenVibe.Events serving `events.app.publish` for app tokens. On 2026-09-23 these were in place on production: a sandbox app uploaded to Media (tenant `prj_…-sandbox`) and published and read app events through public endpoints. That run used curl, not the Codes playgrounds, and it is not yet a committed, repeatable check.@@@ -98,12 +108,23 @@ as they raise the per-address limit.## Deploy (for the lead)++Production deploys with `sudo ovhost deploy codes` on the host (strategy `git-checkout`: fetch,++fast-forward `/opt/openvibe.codes`, install on a lockfile change, restart, wait for `/api/ready`).++The unit is `openvibe-codes.service` on `127.0.0.1:4900`, the env file `/etc/openvibe/codes.env`. State lives in++`/var/lib/openvibe-codes`; nginx serves `openvibe.codes` from++[deploy/nginx/openvibe.codes.conf](deploy/nginx/openvibe.codes.conf).++Rollback: ovhost puts the previous sha back by itself when `/api/ready` does not answer 2xx after the++restart; afterwards `sudo ovhost rollback codes --to <sha>`. One blocker: the trust table was rebuilt++once to the ADR-013 tier names, so a release from before that change expects the old names.++++First install (done once; kept for a rebuild):++1. `git clone` to `/opt/openvibe.codes`; `npm ci --omit=dev` with Node 22.2. `/etc/openvibe/codes.env` from `.env.example` (secrets from the Network client registration).3. `deploy/systemd/openvibe-codes.service` → `/etc/systemd/system/`; `systemctl enable --now openvibe-codes`. State lives in `/var/lib/openvibe-codes`.4. `deploy/nginx/openvibe.codes.conf` → `/etc/nginx/sites-available/`, certificate for `openvibe.codes` + `www`, reload nginx.5. Check `curl -s http://127.0.0.1:4900/api/ready`.--6. Only when the launch rule below holds: remove `openvibe.codes` from `OpenVibe.Sites/sites.json` and switch routing.++6. Only when the launch rule below holds: remove `openvibe.codes` from `OpenVibe.Sites/sites.json` and switch routing (done on 2026-09-23).## Development@@@ -127,7 +148,9 @@ Tests: ADR-013 trust-tier migration; secrets never persisted or re-displayed; NeThe domain keeps its placeholder page on [OpenVibers/OpenVibe.Sites](https://github.com/OpenVibers/OpenVibe.Sites) until all of the following exist (plan §12.12). **Codes left Sites on 2026-09-23 and serves `openvibe.codes`.** The items: an owning runtime with health/readiness and observability (**done**); canonical identity/auth integration (**done; the OAuth client `codes` is registered**); server-rendered public routes useful without JavaScript (**done**); real persistence and end-to-end workflows (**persistence done; the external-developer path ran once on production with curl, not yet through the portal**); capability and event registration against OpenVibe.Contracts (**released**); a migration/seed strategy (none needed: no data is imported; raw old developer keys are never imported), a security review and sitemap/robots behaviour (**sitemap and robots done; the security review is the threat notes below, self-authored**); acceptance tests proving the advertised functionality (**against stand-ins**). Roadmap binding: do not launch Codes as a developer portal while these paths are mocked.--### Threat notes++## Security (threat notes)++++Reporting a vulnerability: [SECURITY.md](SECURITY.md).- Session tokens are httpOnly (unlike the navbar-readable `ov_token` elsewhere) because this site displays secrets; forms carry an HMAC form token and require a same-site `Origin`.- Secrets never reach logs: errors are logged without request bodies; playground failure details are scrubbed of the credential before they are stored or shown.@@@ -7,15 +7,13 @@"runtime": "node 22, express 4, better-sqlite3 11","port": 4900,"domain": "openvibe.codes",-- "packages": [-- "openvibe-contracts v0.33.0",-- "openvibe-sdk v0.5.0",-- "openvibe-shared v1.5.1"-- ],-- "summary": "Deployed and public since 2026-09-23: https://openvibe.codes is served by this portal (openvibe-ovh, unit openvibe-codes on 127.0.0.1:4900 behind nginx, release a9371c3), and the domain left OpenVibe.Sites. Sign-in uses the registered Network OAuth client `codes` (PKCE S256); the principal `codes` holds events.event.publish and the Events relay is configured. It is barely used yet: production holds 0 manifests, 0 releases and 0 playground runs. The external-developer path (account, project, sandbox app, grants, Media upload, app events) was run once on production on 2026-09-23 with public endpoints and curl, not through these playgrounds; that check is not committed to a repository or CI.",++ "contracts": "openvibe-contracts v0.53.0",++ "packages": ["openvibe-contracts v0.53.0", "openvibe-sdk v0.12.0", "openvibe-shared v1.22.0"],++ "summary": "Deployed and public since 2026-09-23: https://openvibe.codes is served by this portal (deployed with `sudo ovhost deploy codes`, unit openvibe-codes on 127.0.0.1:4900 behind nginx), and the domain left OpenVibe.Sites. Sign-in uses the registered Network OAuth client `codes` (PKCE S256); the principal `codes` holds events.event.publish and the Events relay is configured. On 2026-09-23 production held 0 manifests, 0 releases and 0 playground runs. The external-developer path (account, project, sandbox app, grants, Media upload, app events) was run once on production on 2026-09-23 with public endpoints and curl, not through these playgrounds; that check is not committed to a repository or CI.","works": ["Sign-in with OpenVibe.Network (authorization code + PKCE S256), session tokens in httpOnly cookies","Projects, members, apps, credentials (rotate, revoke), grants (request, approve, deny, revoke), quotas and audit over Network's /api/v1/projects API with the person's own token; Network's errors shown as Network answered them",++ "Per-project usage page (owner, admins, staff): Network's GET /api/v1/projects/:project/usage rendered server-side, with quota headroom, published service limits and sampled failures","Project export (one JSON document: Network's project, members, apps, credential ids and hints, grants, quotas, audit for admin+, plus Codes' releases, manifests, trust and playground runs) and delete (owner: archive in Network first, then drafts and playground runs deleted, public releases revoked). Network has no project erasure endpoint, only archive","Full project archive for the owner and admins (roadmap WS-N task 9): one zip with the metadata document (audit included), the release manifests (the project's modules), Media objects (listed with public or 1-hour signed download URLs) and namespaces, and the app events Events still keeps, for production and sandbox; read with Network's read-only export tokens (POST /api/v1/projects/:project/export-tokens, 5 minutes, audited). All or nothing when a service fails; at most CODES_EXPORT_MAX_OBJECTS / CODES_EXPORT_MAX_EVENTS per environment, stated in manifest.json when reached","Client secrets shown once, in the create/rotate response only, with no-store; never stored or logged (tested)",@@@ -31,7 +29,7 @@],"notYet": ["The playgrounds have never been used on production (0 playground runs); the one production end-to-end run used curl, and it is not a committed, repeatable check",-- "No usage, trace or error dashboards: no service reports per-project usage yet; quotas show recorded limits only",++ "Usage covers only what services report in their hourly *.usage.recorded rollups (Network adds them up per day; the current hour is not counted); no trace or error dashboards beyond the sampled failures","Billing sandbox, Chat bot and Realtime playgrounds; CLI and scaffolding; templates","Consent screen for third-party production apps (a Network gap)","No JSON-LD or llms.txt on the public pages",@@@ -41,5 +39,19 @@"serviceManifestRegistered": true,"deployed": true,"placeholderInSites": false,-- "updated": "2026-09-23"++ "updated": "2026-09-28",++ "features": [++ "developer portal over Network's projects, apps, credentials, grants, quotas and audit",++ "per-project usage page from Network's rollups",++ "project export (JSON) and full archive (zip)",++ "secrets shown once, never stored or logged",++ "scope editor offering only grantable capabilities",++ "docs generated from the pinned contracts and SDK",++ "OAuth helper and webhook tester (signature v1 and v2)",++ "grant-respecting Media and Events playgrounds",++ "app and mod manifest validation and release metadata with codes.app.* events",++ "ADR-013 trust tiers",++ "policy and governance pages (governance drafts pending owner review)",++ "per-actor limits (openvibe-sdk/limits)"++ ]}
@@ -47,18 +47,28 @@ Everything is server-rendered and usable without JavaScript. The only scripts of
@@ -47,18 +47,28 @@ Everything is server-rendered and usable without JavaScript. The only scripts of
- **OpenVibe.Network** — SSO (OAuth client `codes`, PKCE S256), JWKS, `/api/v1/projects` (called server-side with the person's Network access token), the registry (`/api/v1/registry/services`, `/.well-known/openvibe`), client-credentials tokens (Codes' own for the events relay; the app's own in playgrounds).
- **OpenVibe.Network** — SSO (OAuth client `codes`, PKCE S256), JWKS, `/api/v1/projects` (called server-side with the person's Network access token), the registry (`/api/v1/registry/services`, `/.well-known/openvibe`), client-credentials tokens (Codes' own for the events relay; the app's own in playgrounds).
- **OpenVibe.Events** — the outbox relay publishes `codes.app.*` with Codes' service token (`events.event.publish`); the Events playground calls it with the app's token (`events.app.publish`); the project archive pulls the project's app events with a Network export token (`events.app.read`).
- **OpenVibe.Events** — the outbox relay publishes `codes.app.*` with Codes' service token (`events.event.publish`); the Events playground calls it with the app's token (`events.app.publish`); the project archive pulls the project's app events with a Network export token (`events.app.read`).
- **OpenVibe.Media** — the Media playground uploads with the app's token into the project's namespace; the project archive lists the project's objects, namespaces and download URLs with a Network export token (`media.object.list`, `media.object.read`).
- **OpenVibe.Media** — the Media playground uploads with the app's token into the project's namespace; the project archive lists the project's objects, namespaces and download URLs with a Network export token (`media.object.list`, `media.object.read`).
-- **openvibe-contracts** v0.33.0, **openvibe-sdk v0.5.0**, **openvibe-shared v1.5.1** (pinned tag tarballs; the docs show the tag and the package version, and say so when they differ).
+- **openvibe-contracts** v0.53.0, **openvibe-sdk v0.12.0**, **openvibe-shared v1.22.0** (pinned tag tarballs; the docs show the tag and the package version, and say so when they differ).
No path in Codes sends or accepts a shared loopback key (tested by grep and at runtime).
No path in Codes sends or accepts a shared loopback key (tested by grep and at runtime).
## Grants and registration the lead must add
## Grants and registration the lead must add
+Implemented here (the service manifest's `capabilities`): `codes.release.read` (public release reads;
+no token needed, a presented token must hold it) and `codes.release.manage` (release management by an
+app with its own token), both guarded with openvibe-contracts `requireCapability`.
+
+Called elsewhere: as the service principal `codes`, `events.event.publish` at Events (the outbox relay);
+as the signed-in person, with their own Network token, Network's `/api/v1/projects`; as the app, with
+its own token, `media.object.upload` (Media) and `events.app.publish` (Events) in the playgrounds; and,
+for the project archive, Network's read-only export tokens holding `events.app.read`,
+`media.object.list` and `media.object.read`.
+
In Network (`server/identity/principals.js` / `server/db/database.js`, as for coupons and host):
In Network (`server/identity/principals.js` / `server/db/database.js`, as for coupons and host):
- OAuth client `codes`, name `OpenVibe.Codes`, redirect URI `https://openvibe.codes/auth/callback`.
- OAuth client `codes`, name `OpenVibe.Codes`, redirect URI `https://openvibe.codes/auth/callback`.
- Service grant `['codes', 'events.event.publish', 'openvibe.events', []]` (the outbox relay).
- Service grant `['codes', 'events.event.publish', 'openvibe.events', []]` (the outbox relay).
-The Codes service manifest, `codes.release.manage|read` and `codes.app-manifest@1` are released in openvibe-contracts (tag v0.27.0; this repository pins v0.33.0); the CI contracts check is blocking.
+The Codes service manifest, `codes.release.manage|read` and `codes.app-manifest@1` are released in openvibe-contracts (tag v0.27.0; this repository pins v0.53.0); the CI contracts check is blocking.
For the playgrounds to succeed end to end (not Codes' code; configuration elsewhere): Network `DEV_SANDBOX_AUDIENCES` including `openvibe.media` and `openvibe.events`, a staff-set allowance containing `media.object.upload` and `events.app.publish` for the project, a Media tenant keyed by the project id, and OpenVibe.Events serving `events.app.publish` for app tokens. On 2026-09-23 these were in place on production: a sandbox app uploaded to Media (tenant `prj_…-sandbox`) and published and read app events through public endpoints. That run used curl, not the Codes playgrounds, and it is not yet a committed, repeatable check.
For the playgrounds to succeed end to end (not Codes' code; configuration elsewhere): Network `DEV_SANDBOX_AUDIENCES` including `openvibe.media` and `openvibe.events`, a staff-set allowance containing `media.object.upload` and `events.app.publish` for the project, a Media tenant keyed by the project id, and OpenVibe.Events serving `events.app.publish` for app tokens. On 2026-09-23 these were in place on production: a sandbox app uploaded to Media (tenant `prj_…-sandbox`) and published and read app events through public endpoints. That run used curl, not the Codes playgrounds, and it is not yet a committed, repeatable check.
@@ -98,12 +108,23 @@ as they raise the per-address limit.
@@ -98,12 +108,23 @@ as they raise the per-address limit.
## Deploy (for the lead)
## Deploy (for the lead)
+Production deploys with `sudo ovhost deploy codes` on the host (strategy `git-checkout`: fetch,
+fast-forward `/opt/openvibe.codes`, install on a lockfile change, restart, wait for `/api/ready`).
+The unit is `openvibe-codes.service` on `127.0.0.1:4900`, the env file `/etc/openvibe/codes.env`. State lives in
+`/var/lib/openvibe-codes`; nginx serves `openvibe.codes` from
+[deploy/nginx/openvibe.codes.conf](deploy/nginx/openvibe.codes.conf).
+Rollback: ovhost puts the previous sha back by itself when `/api/ready` does not answer 2xx after the
+restart; afterwards `sudo ovhost rollback codes --to <sha>`. One blocker: the trust table was rebuilt
+once to the ADR-013 tier names, so a release from before that change expects the old names.
+
+First install (done once; kept for a rebuild):
+
1. `git clone` to `/opt/openvibe.codes`; `npm ci --omit=dev` with Node 22.
1. `git clone` to `/opt/openvibe.codes`; `npm ci --omit=dev` with Node 22.
2. `/etc/openvibe/codes.env` from `.env.example` (secrets from the Network client registration).
2. `/etc/openvibe/codes.env` from `.env.example` (secrets from the Network client registration).
3. `deploy/systemd/openvibe-codes.service` → `/etc/systemd/system/`; `systemctl enable --now openvibe-codes`. State lives in `/var/lib/openvibe-codes`.
3. `deploy/systemd/openvibe-codes.service` → `/etc/systemd/system/`; `systemctl enable --now openvibe-codes`. State lives in `/var/lib/openvibe-codes`.
4. `deploy/nginx/openvibe.codes.conf` → `/etc/nginx/sites-available/`, certificate for `openvibe.codes` + `www`, reload nginx.
4. `deploy/nginx/openvibe.codes.conf` → `/etc/nginx/sites-available/`, certificate for `openvibe.codes` + `www`, reload nginx.
5. Check `curl -s http://127.0.0.1:4900/api/ready`.
5. Check `curl -s http://127.0.0.1:4900/api/ready`.
-6. Only when the launch rule below holds: remove `openvibe.codes` from `OpenVibe.Sites/sites.json` and switch routing.
+6. Only when the launch rule below holds: remove `openvibe.codes` from `OpenVibe.Sites/sites.json` and switch routing (done on 2026-09-23).
## Development
## Development
@@ -127,7 +148,9 @@ Tests: ADR-013 trust-tier migration; secrets never persisted or re-displayed; Ne
@@ -127,7 +148,9 @@ Tests: ADR-013 trust-tier migration; secrets never persisted or re-displayed; Ne
The domain keeps its placeholder page on [OpenVibers/OpenVibe.Sites](https://github.com/OpenVibers/OpenVibe.Sites) until all of the following exist (plan §12.12). **Codes left Sites on 2026-09-23 and serves `openvibe.codes`.** The items: an owning runtime with health/readiness and observability (**done**); canonical identity/auth integration (**done; the OAuth client `codes` is registered**); server-rendered public routes useful without JavaScript (**done**); real persistence and end-to-end workflows (**persistence done; the external-developer path ran once on production with curl, not yet through the portal**); capability and event registration against OpenVibe.Contracts (**released**); a migration/seed strategy (none needed: no data is imported; raw old developer keys are never imported), a security review and sitemap/robots behaviour (**sitemap and robots done; the security review is the threat notes below, self-authored**); acceptance tests proving the advertised functionality (**against stand-ins**). Roadmap binding: do not launch Codes as a developer portal while these paths are mocked.
The domain keeps its placeholder page on [OpenVibers/OpenVibe.Sites](https://github.com/OpenVibers/OpenVibe.Sites) until all of the following exist (plan §12.12). **Codes left Sites on 2026-09-23 and serves `openvibe.codes`.** The items: an owning runtime with health/readiness and observability (**done**); canonical identity/auth integration (**done; the OAuth client `codes` is registered**); server-rendered public routes useful without JavaScript (**done**); real persistence and end-to-end workflows (**persistence done; the external-developer path ran once on production with curl, not yet through the portal**); capability and event registration against OpenVibe.Contracts (**released**); a migration/seed strategy (none needed: no data is imported; raw old developer keys are never imported), a security review and sitemap/robots behaviour (**sitemap and robots done; the security review is the threat notes below, self-authored**); acceptance tests proving the advertised functionality (**against stand-ins**). Roadmap binding: do not launch Codes as a developer portal while these paths are mocked.
-### Threat notes
+## Security (threat notes)
+
+Reporting a vulnerability: [SECURITY.md](SECURITY.md).
- Session tokens are httpOnly (unlike the navbar-readable `ov_token` elsewhere) because this site displays secrets; forms carry an HMAC form token and require a same-site `Origin`.
- Session tokens are httpOnly (unlike the navbar-readable `ov_token` elsewhere) because this site displays secrets; forms carry an HMAC form token and require a same-site `Origin`.
- Secrets never reach logs: errors are logged without request bodies; playground failure details are scrubbed of the credential before they are stored or shown.
- Secrets never reach logs: errors are logged without request bodies; playground failure details are scrubbed of the credential before they are stored or shown.
@@ -7,15 +7,13 @@
@@ -7,15 +7,13 @@
"runtime": "node 22, express 4, better-sqlite3 11",
"runtime": "node 22, express 4, better-sqlite3 11",
"port": 4900,
"port": 4900,
"domain": "openvibe.codes",
"domain": "openvibe.codes",
- "packages": [
- "openvibe-contracts v0.33.0",
- "openvibe-sdk v0.5.0",
- "openvibe-shared v1.5.1"
- ],
- "summary": "Deployed and public since 2026-09-23: https://openvibe.codes is served by this portal (openvibe-ovh, unit openvibe-codes on 127.0.0.1:4900 behind nginx, release a9371c3), and the domain left OpenVibe.Sites. Sign-in uses the registered Network OAuth client `codes` (PKCE S256); the principal `codes` holds events.event.publish and the Events relay is configured. It is barely used yet: production holds 0 manifests, 0 releases and 0 playground runs. The external-developer path (account, project, sandbox app, grants, Media upload, app events) was run once on production on 2026-09-23 with public endpoints and curl, not through these playgrounds; that check is not committed to a repository or CI.",
+ "contracts": "openvibe-contracts v0.53.0",
+ "packages": ["openvibe-contracts v0.53.0", "openvibe-sdk v0.12.0", "openvibe-shared v1.22.0"],
+ "summary": "Deployed and public since 2026-09-23: https://openvibe.codes is served by this portal (deployed with `sudo ovhost deploy codes`, unit openvibe-codes on 127.0.0.1:4900 behind nginx), and the domain left OpenVibe.Sites. Sign-in uses the registered Network OAuth client `codes` (PKCE S256); the principal `codes` holds events.event.publish and the Events relay is configured. On 2026-09-23 production held 0 manifests, 0 releases and 0 playground runs. The external-developer path (account, project, sandbox app, grants, Media upload, app events) was run once on production on 2026-09-23 with public endpoints and curl, not through these playgrounds; that check is not committed to a repository or CI.",
"works": [
"works": [
"Sign-in with OpenVibe.Network (authorization code + PKCE S256), session tokens in httpOnly cookies",
"Sign-in with OpenVibe.Network (authorization code + PKCE S256), session tokens in httpOnly cookies",
"Projects, members, apps, credentials (rotate, revoke), grants (request, approve, deny, revoke), quotas and audit over Network's /api/v1/projects API with the person's own token; Network's errors shown as Network answered them",
"Projects, members, apps, credentials (rotate, revoke), grants (request, approve, deny, revoke), quotas and audit over Network's /api/v1/projects API with the person's own token; Network's errors shown as Network answered them",
+ "Per-project usage page (owner, admins, staff): Network's GET /api/v1/projects/:project/usage rendered server-side, with quota headroom, published service limits and sampled failures",
"Project export (one JSON document: Network's project, members, apps, credential ids and hints, grants, quotas, audit for admin+, plus Codes' releases, manifests, trust and playground runs) and delete (owner: archive in Network first, then drafts and playground runs deleted, public releases revoked). Network has no project erasure endpoint, only archive",
"Project export (one JSON document: Network's project, members, apps, credential ids and hints, grants, quotas, audit for admin+, plus Codes' releases, manifests, trust and playground runs) and delete (owner: archive in Network first, then drafts and playground runs deleted, public releases revoked). Network has no project erasure endpoint, only archive",
"Full project archive for the owner and admins (roadmap WS-N task 9): one zip with the metadata document (audit included), the release manifests (the project's modules), Media objects (listed with public or 1-hour signed download URLs) and namespaces, and the app events Events still keeps, for production and sandbox; read with Network's read-only export tokens (POST /api/v1/projects/:project/export-tokens, 5 minutes, audited). All or nothing when a service fails; at most CODES_EXPORT_MAX_OBJECTS / CODES_EXPORT_MAX_EVENTS per environment, stated in manifest.json when reached",
"Full project archive for the owner and admins (roadmap WS-N task 9): one zip with the metadata document (audit included), the release manifests (the project's modules), Media objects (listed with public or 1-hour signed download URLs) and namespaces, and the app events Events still keeps, for production and sandbox; read with Network's read-only export tokens (POST /api/v1/projects/:project/export-tokens, 5 minutes, audited). All or nothing when a service fails; at most CODES_EXPORT_MAX_OBJECTS / CODES_EXPORT_MAX_EVENTS per environment, stated in manifest.json when reached",
"Client secrets shown once, in the create/rotate response only, with no-store; never stored or logged (tested)",
"Client secrets shown once, in the create/rotate response only, with no-store; never stored or logged (tested)",
@@ -31,7 +29,7 @@
@@ -31,7 +29,7 @@
],
],
"notYet": [
"notYet": [
"The playgrounds have never been used on production (0 playground runs); the one production end-to-end run used curl, and it is not a committed, repeatable check",
"The playgrounds have never been used on production (0 playground runs); the one production end-to-end run used curl, and it is not a committed, repeatable check",
- "No usage, trace or error dashboards: no service reports per-project usage yet; quotas show recorded limits only",
+ "Usage covers only what services report in their hourly *.usage.recorded rollups (Network adds them up per day; the current hour is not counted); no trace or error dashboards beyond the sampled failures",
"Billing sandbox, Chat bot and Realtime playgrounds; CLI and scaffolding; templates",
"Billing sandbox, Chat bot and Realtime playgrounds; CLI and scaffolding; templates",
"Consent screen for third-party production apps (a Network gap)",
"Consent screen for third-party production apps (a Network gap)",
"No JSON-LD or llms.txt on the public pages",
"No JSON-LD or llms.txt on the public pages",
@@ -41,5 +39,19 @@
@@ -41,5 +39,19 @@
"serviceManifestRegistered": true,
"serviceManifestRegistered": true,
"deployed": true,
"deployed": true,
"placeholderInSites": false,
"placeholderInSites": false,
- "updated": "2026-09-23"
+ "updated": "2026-09-28",
+ "features": [
+ "developer portal over Network's projects, apps, credentials, grants, quotas and audit",
+ "per-project usage page from Network's rollups",
+ "project export (JSON) and full archive (zip)",
+ "secrets shown once, never stored or logged",
+ "scope editor offering only grantable capabilities",
+ "docs generated from the pinned contracts and SDK",
+ "OAuth helper and webhook tester (signature v1 and v2)",
+ "grant-respecting Media and Events playgrounds",
+ "app and mod manifest validation and release metadata with codes.app.* events",
+ "ADR-013 trust tiers",
+ "policy and governance pages (governance drafts pending owner review)",
+ "per-actor limits (openvibe-sdk/limits)"
+ ]
}
}