openvibers/openvibe.contracts Commits
v0.27.0: OpenVibe.Codes is alpha — codes.app-manifest@1, codes.release.manage|read
Changes
@@@ -157,6 +157,16 @@"compatibility": "backward","status": "active","adr": "ADR-013"++ },++ {++ "id": "codes.app-manifest",++ "version": "1.0.0",++ "owner": "codes",++ "schema": "codes/app-manifest.v1.json",++ "visibility": "public",++ "compatibility": "backward",++ "status": "active",++ "adr": "ADR-014"}]}nnew file mode 100644@@@ -0,0 +1,68 @@++{++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/codes/app-manifest.v1.json",++ "title": "AppManifest",++ "description": "PROPOSAL (OpenVibe.Codes, roadmap Wave 20): an app release as the platform knows it. The app is a Network developer app (ADR-014): its id is the Network app id, its capabilities are only a request (the grants in Network are the authority), and trust tiers are metadata that never change a grant check. OpenVibe.Codes validates with this schema, loaded into openvibe-contracts' validator, until Contracts publishes it as codes.app-manifest@1.",++ "type": "object",++ "required": ["id", "name", "version", "publisher", "project_id", "capabilities", "compatibility"],++ "additionalProperties": false,++ "properties": {++ "id": {++ "type": "string",++ "pattern": "^app_[0-9A-HJKMNP-TV-Z]{26}$",++ "description": "The Network app id (its client_id). Its principal subject is app:<id>."++ },++ "name": { "type": "string", "minLength": 1, "maxLength": 80 },++ "version": {++ "type": "string",++ "pattern": "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)(-[0-9A-Za-z.-]+)?$",++ "description": "Semantic version of this release."++ },++ "description": { "type": "string", "maxLength": 1000 },++ "publisher": {++ "$ref": "../identity/subject-ref.v1.json",++ "description": "Who publishes the release: the app itself or a member of its project."++ },++ "project_id": {++ "type": "string",++ "pattern": "^prj_[0-9A-HJKMNP-TV-Z]{26}$",++ "description": "The Network project that owns the app. Tenancy in other services is keyed by it (ADR-014)."++ },++ "environment": { "enum": ["sandbox", "production"], "description": "The app's environment. Apps never change environment." },++ "capabilities": {++ "description": "Capability ids the app asks for (3+ segments). Only active public (or partner, by staff allowance) capabilities can ever be granted to apps.",++ "type": "array",++ "maxItems": 64,++ "uniqueItems": true,++ "items": { "type": "string", "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+){2,}$" }++ },++ "events": {++ "type": "object",++ "additionalProperties": false,++ "properties": {++ "consumes": {++ "description": "Event types (or a trailing .* family) the app subscribes to.",++ "type": "array", "maxItems": 64, "uniqueItems": true,++ "items": { "type": "string", "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+)*(\\.\\*)?$" }++ }++ }++ },++ "redirect_uris": {++ "description": "Informational copy of the redirect URIs registered in Network (Network's list is the authority).",++ "type": "array", "maxItems": 10, "uniqueItems": true,++ "items": { "type": "string", "maxLength": 500 }++ },++ "homepage": { "type": "string", "pattern": "^https://[^\\s]{1,2000}$" },++ "repository": { "type": "string", "pattern": "^https://[^\\s]{1,2000}$" },++ "license": { "type": "string", "minLength": 1, "maxLength": 100, "description": "SPDX license expression." },++ "compatibility": {++ "type": "object",++ "required": ["contracts"],++ "additionalProperties": false,++ "properties": {++ "contracts": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Semver range of openvibe-contracts releases it was built against." },++ "sdk": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Semver range of openvibe-sdk releases it uses." }++ }++ }++ }++}nnew file mode 100644@@@ -0,0 +1,16 @@++{++ "id": "app_lowercase",++ "name": "My app",++ "version": "0.1.0",++ "publisher": {++ "type": "app",++ "id": "app_01JABCDEFGHJKMNPQRSTVWXYZ0"++ },++ "project_id": "prj_01JABCDEFGHJKMNPQRSTVWXYZ0",++ "environment": "sandbox",++ "capabilities": [],++ "compatibility": {++ "contracts": "^0.26.0",++ "sdk": "^0.2.2"++ }++}\\ No newline at end of filennew file mode 100644@@@ -0,0 +1,13 @@++{++ "id": "app_01JABCDEFGHJKMNPQRSTVWXYZ0",++ "name": "My app",++ "version": "0.1.0",++ "publisher": {++ "type": "app",++ "id": "app_01JABCDEFGHJKMNPQRSTVWXYZ0"++ },++ "project_id": "prj_01JABCDEFGHJKMNPQRSTVWXYZ0",++ "environment": "sandbox",++ "capabilities": [],++ "compatibility": {}++}\\ No newline at end of filennew file mode 100644@@@ -0,0 +1,16 @@++{++ "id": "app_01JABCDEFGHJKMNPQRSTVWXYZ0",++ "name": "My app",++ "version": "0.1.0",++ "publisher": {++ "type": "app",++ "id": "app_01JABCDEFGHJKMNPQRSTVWXYZ0"++ },++ "project_id": "prj_01JABCDEFGHJKMNPQRSTVWXYZ0",++ "environment": "sandbox",++ "capabilities": [],++ "compatibility": {++ "contracts": "^0.26.0",++ "sdk": "^0.2.2"++ }++}@@@ -1837,6 +1837,136 @@}}}++ },++ "codes.app-manifest": {++ "version": "1.0.0",++ "owner": "codes",++ "status": "active",++ "schema": {++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/codes/app-manifest.v1.json",++ "title": "AppManifest",++ "description": "PROPOSAL (OpenVibe.Codes, roadmap Wave 20): an app release as the platform knows it. The app is a Network developer app (ADR-014): its id is the Network app id, its capabilities are only a request (the grants in Network are the authority), and trust tiers are metadata that never change a grant check. OpenVibe.Codes validates with this schema, loaded into openvibe-contracts' validator, until Contracts publishes it as codes.app-manifest@1.",++ "type": "object",++ "required": [++ "id",++ "name",++ "version",++ "publisher",++ "project_id",++ "capabilities",++ "compatibility"++ ],++ "additionalProperties": false,++ "properties": {++ "id": {++ "type": "string",++ "pattern": "^app_[0-9A-HJKMNP-TV-Z]{26}$",++ "description": "The Network app id (its client_id). Its principal subject is app:<id>."++ },++ "name": {++ "type": "string",++ "minLength": 1,++ "maxLength": 80++ },++ "version": {++ "type": "string",++ "pattern": "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)(-[0-9A-Za-z.-]+)?$",++ "description": "Semantic version of this release."++ },++ "description": {++ "type": "string",++ "maxLength": 1000++ },++ "publisher": {++ "$ref": "../identity/subject-ref.v1.json",++ "description": "Who publishes the release: the app itself or a member of its project."++ },++ "project_id": {++ "type": "string",++ "pattern": "^prj_[0-9A-HJKMNP-TV-Z]{26}$",++ "description": "The Network project that owns the app. Tenancy in other services is keyed by it (ADR-014)."++ },++ "environment": {++ "enum": [++ "sandbox",++ "production"++ ],++ "description": "The app's environment. Apps never change environment."++ },++ "capabilities": {++ "description": "Capability ids the app asks for (3+ segments). Only active public (or partner, by staff allowance) capabilities can ever be granted to apps.",++ "type": "array",++ "maxItems": 64,++ "uniqueItems": true,++ "items": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+){2,}$"++ }++ },++ "events": {++ "type": "object",++ "additionalProperties": false,++ "properties": {++ "consumes": {++ "description": "Event types (or a trailing .* family) the app subscribes to.",++ "type": "array",++ "maxItems": 64,++ "uniqueItems": true,++ "items": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+)*(\\.\\*)?$"++ }++ }++ }++ },++ "redirect_uris": {++ "description": "Informational copy of the redirect URIs registered in Network (Network's list is the authority).",++ "type": "array",++ "maxItems": 10,++ "uniqueItems": true,++ "items": {++ "type": "string",++ "maxLength": 500++ }++ },++ "homepage": {++ "type": "string",++ "pattern": "^https://[^\\s]{1,2000}$"++ },++ "repository": {++ "type": "string",++ "pattern": "^https://[^\\s]{1,2000}$"++ },++ "license": {++ "type": "string",++ "minLength": 1,++ "maxLength": 100,++ "description": "SPDX license expression."++ },++ "compatibility": {++ "type": "object",++ "required": [++ "contracts"++ ],++ "additionalProperties": false,++ "properties": {++ "contracts": {++ "type": "string",++ "minLength": 1,++ "maxLength": 100,++ "description": "Semver range of openvibe-contracts releases it was built against."++ },++ "sdk": {++ "type": "string",++ "minLength": 1,++ "maxLength": 100,++ "description": "Semver range of openvibe-sdk releases it uses."++ }++ }++ }++ }++ }}}}@@@ -3298,3 +3298,76 @@ export interface ModManifest {};homepage?: string;}++++/** [email protected] (owner: codes) */++/**++ * PROPOSAL (OpenVibe.Codes, roadmap Wave 20): an app release as the platform knows it. The app is a Network developer app (ADR-014): its id is the Network app id, its capabilities are only a request (the grants in Network are the authority), and trust tiers are metadata that never change a grant check. OpenVibe.Codes validates with this schema, loaded into openvibe-contracts' validator, until Contracts publishes it as codes.app-manifest@1.++ */++export interface AppManifest {++ /**++ * The Network app id (its client_id). Its principal subject is app:<id>.++ */++ id: string;++ name: string;++ /**++ * Semantic version of this release.++ */++ version: string;++ description?: string;++ publisher: SubjectRef;++ /**++ * The Network project that owns the app. Tenancy in other services is keyed by it (ADR-014).++ */++ project_id: string;++ /**++ * The app's environment. Apps never change environment.++ */++ environment?: "sandbox" | "production";++ /**++ * Capability ids the app asks for (3+ segments). Only active public (or partner, by staff allowance) capabilities can ever be granted to apps.++ *++ * @maxItems 64++ */++ capabilities: string[];++ events?: {++ /**++ * Event types (or a trailing .* family) the app subscribes to.++ *++ * @maxItems 64++ */++ consumes?: string[];++ };++ /**++ * Informational copy of the redirect URIs registered in Network (Network's list is the authority).++ *++ * @maxItems 10++ */++ redirect_uris?:++ | []++ | [string]++ | [string, string]++ | [string, string, string]++ | [string, string, string, string]++ | [string, string, string, string, string]++ | [string, string, string, string, string, string]++ | [string, string, string, string, string, string, string]++ | [string, string, string, string, string, string, string, string]++ | [string, string, string, string, string, string, string, string, string]++ | [string, string, string, string, string, string, string, string, string, string];++ homepage?: string;++ repository?: string;++ /**++ * SPDX license expression.++ */++ license?: string;++ compatibility: {++ /**++ * Semver range of openvibe-contracts releases it was built against.++ */++ contracts: string;++ /**++ * Semver range of openvibe-sdk releases it uses.++ */++ sdk?: string;++ };++}nnew file mode 100644@@@ -0,0 +1,19 @@++{++ "id": "codes.release.manage",++ "version": "1.0",++ "owner": "codes",++ "status": "active",++ "visibility": "public",++ "description": "An app manages release metadata for ITSELF with its own token (audience openvibe.codes): create a release from a validated app or mod manifest, publish, deprecate (with a reason and an optional replacement) and revoke it. The token's sub must be app:<the app in the path>; people manage releases in the portal with their project role instead. Trust tiers are not part of this capability (staff metadata only).",++ "inputSchema": "codes.app-manifest@1",++ "permissions": ["codes:releases:write"],++ "resourceConstraints": ["owner", "project"],++ "quotaClass": "codes-release-write",++ "events": ["codes.app.published", "codes.app.deprecated", "codes.app.revoked"],++ "implementedBy": [++ "POST /api/v1/apps/:app/releases",++ "POST /api/v1/releases/:id/publish",++ "POST /api/v1/releases/:id/deprecate",++ "POST /api/v1/releases/:id/revoke"++ ]++}nnew file mode 100644@@@ -0,0 +1,18 @@++{++ "id": "codes.release.read",++ "version": "1.0",++ "owner": "codes",++ "status": "active",++ "visibility": "public",++ "description": "Read public release metadata: an app's published, deprecated and revoked releases with their manifests, compatibility ranges and the app's trust tier (metadata only; it never grants anything). Drafts are never returned. Public; no token needed.",++ "outputSchema": "codes.app-manifest@1",++ "permissions": ["codes:releases:read"],++ "resourceConstraints": ["none"],++ "quotaClass": "codes-read",++ "events": [],++ "implementedBy": [++ "GET /api/v1/apps/:app/releases",++ "GET /api/v1/apps/:app/trust",++ "GET /api/v1/releases/:id"++ ]++}@@@ -1,16 +1,30 @@{"version": "0.1.0","contractRanges": {-- "openvibe-contracts": "^0.1.0"++ "openvibe-contracts": ">=0.26.0 <1.0.0"},"id": "codes","name": "OpenVibe.Codes",-- "status": "placeholder",++ "status": "alpha","repository": "OpenVibers/OpenVibe.Codes",-- "domains": [],-- "capabilities": [],-- "eventsProduced": [],++ "domains": [++ "openvibe.codes"++ ],++ "publicOrigin": "https://openvibe.codes",++ "health": "/api/health",++ "ready": "/api/ready",++ "capabilities": [++ "codes.release.read",++ "codes.release.manage"++ ],++ "eventsProduced": [++ "codes.app.published",++ "codes.app.deprecated",++ "codes.app.revoked"++ ],"eventsConsumed": [],-- "namespacesOwned": [],-- "notes": "The developer portal: registry and contract explorers, credentials, playgrounds, examples, mod/app publishing, governance. Charter only; no runtime."++ "namespacesOwned": [++ "codes.*"++ ],++ "notes": "Port 4900, unit openvibe-codes.service, state /var/lib/openvibe-codes. The developer portal (ADR-014): projects, members, apps, credentials, grants and quotas are OWNED BY NETWORK and shown through Network's /api/v1/projects API with the signed-in person's own token; Codes stores none of them and never a secret. Codes owns only manifests, releases (+ append-only release_log), trust tiers (metadata) and playground run logs in its own SQLite. Consumes OpenVibe.Network (SSO with PKCE S256 as OAuth client codes, JWKS, the projects API, the registry, client-credentials) and publishes through OpenVibe.Events (events.event.publish). Playgrounds call Events and Media with the APP's own token only. Docs are generated at boot from the pinned openvibe-contracts and openvibe-sdk."}
@@ -157,6 +157,16 @@
@@ -157,6 +157,16 @@
"compatibility": "backward",
"compatibility": "backward",
"status": "active",
"status": "active",
"adr": "ADR-013"
"adr": "ADR-013"
+ },
+ {
+ "id": "codes.app-manifest",
+ "version": "1.0.0",
+ "owner": "codes",
+ "schema": "codes/app-manifest.v1.json",
+ "visibility": "public",
+ "compatibility": "backward",
+ "status": "active",
+ "adr": "ADR-014"
}
}
]
]
}
}
new file mode 100644
new file mode 100644
@@ -0,0 +1,68 @@
@@ -0,0 +1,68 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/codes/app-manifest.v1.json",
+ "title": "AppManifest",
+ "description": "PROPOSAL (OpenVibe.Codes, roadmap Wave 20): an app release as the platform knows it. The app is a Network developer app (ADR-014): its id is the Network app id, its capabilities are only a request (the grants in Network are the authority), and trust tiers are metadata that never change a grant check. OpenVibe.Codes validates with this schema, loaded into openvibe-contracts' validator, until Contracts publishes it as codes.app-manifest@1.",
+ "type": "object",
+ "required": ["id", "name", "version", "publisher", "project_id", "capabilities", "compatibility"],
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "pattern": "^app_[0-9A-HJKMNP-TV-Z]{26}$",
+ "description": "The Network app id (its client_id). Its principal subject is app:<id>."
+ },
+ "name": { "type": "string", "minLength": 1, "maxLength": 80 },
+ "version": {
+ "type": "string",
+ "pattern": "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)(-[0-9A-Za-z.-]+)?$",
+ "description": "Semantic version of this release."
+ },
+ "description": { "type": "string", "maxLength": 1000 },
+ "publisher": {
+ "$ref": "../identity/subject-ref.v1.json",
+ "description": "Who publishes the release: the app itself or a member of its project."
+ },
+ "project_id": {
+ "type": "string",
+ "pattern": "^prj_[0-9A-HJKMNP-TV-Z]{26}$",
+ "description": "The Network project that owns the app. Tenancy in other services is keyed by it (ADR-014)."
+ },
+ "environment": { "enum": ["sandbox", "production"], "description": "The app's environment. Apps never change environment." },
+ "capabilities": {
+ "description": "Capability ids the app asks for (3+ segments). Only active public (or partner, by staff allowance) capabilities can ever be granted to apps.",
+ "type": "array",
+ "maxItems": 64,
+ "uniqueItems": true,
+ "items": { "type": "string", "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+){2,}$" }
+ },
+ "events": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "consumes": {
+ "description": "Event types (or a trailing .* family) the app subscribes to.",
+ "type": "array", "maxItems": 64, "uniqueItems": true,
+ "items": { "type": "string", "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+)*(\\.\\*)?$" }
+ }
+ }
+ },
+ "redirect_uris": {
+ "description": "Informational copy of the redirect URIs registered in Network (Network's list is the authority).",
+ "type": "array", "maxItems": 10, "uniqueItems": true,
+ "items": { "type": "string", "maxLength": 500 }
+ },
+ "homepage": { "type": "string", "pattern": "^https://[^\\s]{1,2000}$" },
+ "repository": { "type": "string", "pattern": "^https://[^\\s]{1,2000}$" },
+ "license": { "type": "string", "minLength": 1, "maxLength": 100, "description": "SPDX license expression." },
+ "compatibility": {
+ "type": "object",
+ "required": ["contracts"],
+ "additionalProperties": false,
+ "properties": {
+ "contracts": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Semver range of openvibe-contracts releases it was built against." },
+ "sdk": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Semver range of openvibe-sdk releases it uses." }
+ }
+ }
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
+{
+ "id": "app_lowercase",
+ "name": "My app",
+ "version": "0.1.0",
+ "publisher": {
+ "type": "app",
+ "id": "app_01JABCDEFGHJKMNPQRSTVWXYZ0"
+ },
+ "project_id": "prj_01JABCDEFGHJKMNPQRSTVWXYZ0",
+ "environment": "sandbox",
+ "capabilities": [],
+ "compatibility": {
+ "contracts": "^0.26.0",
+ "sdk": "^0.2.2"
+ }
+}
\ No newline at end of file
\ No newline at end of file
new file mode 100644
new file mode 100644
@@ -0,0 +1,13 @@
@@ -0,0 +1,13 @@
+{
+ "id": "app_01JABCDEFGHJKMNPQRSTVWXYZ0",
+ "name": "My app",
+ "version": "0.1.0",
+ "publisher": {
+ "type": "app",
+ "id": "app_01JABCDEFGHJKMNPQRSTVWXYZ0"
+ },
+ "project_id": "prj_01JABCDEFGHJKMNPQRSTVWXYZ0",
+ "environment": "sandbox",
+ "capabilities": [],
+ "compatibility": {}
+}
\ No newline at end of file
\ No newline at end of file
new file mode 100644
new file mode 100644
@@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
+{
+ "id": "app_01JABCDEFGHJKMNPQRSTVWXYZ0",
+ "name": "My app",
+ "version": "0.1.0",
+ "publisher": {
+ "type": "app",
+ "id": "app_01JABCDEFGHJKMNPQRSTVWXYZ0"
+ },
+ "project_id": "prj_01JABCDEFGHJKMNPQRSTVWXYZ0",
+ "environment": "sandbox",
+ "capabilities": [],
+ "compatibility": {
+ "contracts": "^0.26.0",
+ "sdk": "^0.2.2"
+ }
+}
@@ -1837,6 +1837,136 @@
@@ -1837,6 +1837,136 @@
}
}
}
}
}
}
+ },
+ "codes.app-manifest": {
+ "version": "1.0.0",
+ "owner": "codes",
+ "status": "active",
+ "schema": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/codes/app-manifest.v1.json",
+ "title": "AppManifest",
+ "description": "PROPOSAL (OpenVibe.Codes, roadmap Wave 20): an app release as the platform knows it. The app is a Network developer app (ADR-014): its id is the Network app id, its capabilities are only a request (the grants in Network are the authority), and trust tiers are metadata that never change a grant check. OpenVibe.Codes validates with this schema, loaded into openvibe-contracts' validator, until Contracts publishes it as codes.app-manifest@1.",
+ "type": "object",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "publisher",
+ "project_id",
+ "capabilities",
+ "compatibility"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "pattern": "^app_[0-9A-HJKMNP-TV-Z]{26}$",
+ "description": "The Network app id (its client_id). Its principal subject is app:<id>."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 80
+ },
+ "version": {
+ "type": "string",
+ "pattern": "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)(-[0-9A-Za-z.-]+)?$",
+ "description": "Semantic version of this release."
+ },
+ "description": {
+ "type": "string",
+ "maxLength": 1000
+ },
+ "publisher": {
+ "$ref": "../identity/subject-ref.v1.json",
+ "description": "Who publishes the release: the app itself or a member of its project."
+ },
+ "project_id": {
+ "type": "string",
+ "pattern": "^prj_[0-9A-HJKMNP-TV-Z]{26}$",
+ "description": "The Network project that owns the app. Tenancy in other services is keyed by it (ADR-014)."
+ },
+ "environment": {
+ "enum": [
+ "sandbox",
+ "production"
+ ],
+ "description": "The app's environment. Apps never change environment."
+ },
+ "capabilities": {
+ "description": "Capability ids the app asks for (3+ segments). Only active public (or partner, by staff allowance) capabilities can ever be granted to apps.",
+ "type": "array",
+ "maxItems": 64,
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+){2,}$"
+ }
+ },
+ "events": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "consumes": {
+ "description": "Event types (or a trailing .* family) the app subscribes to.",
+ "type": "array",
+ "maxItems": 64,
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+)*(\\.\\*)?$"
+ }
+ }
+ }
+ },
+ "redirect_uris": {
+ "description": "Informational copy of the redirect URIs registered in Network (Network's list is the authority).",
+ "type": "array",
+ "maxItems": 10,
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "maxLength": 500
+ }
+ },
+ "homepage": {
+ "type": "string",
+ "pattern": "^https://[^\\s]{1,2000}$"
+ },
+ "repository": {
+ "type": "string",
+ "pattern": "^https://[^\\s]{1,2000}$"
+ },
+ "license": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 100,
+ "description": "SPDX license expression."
+ },
+ "compatibility": {
+ "type": "object",
+ "required": [
+ "contracts"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "contracts": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 100,
+ "description": "Semver range of openvibe-contracts releases it was built against."
+ },
+ "sdk": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 100,
+ "description": "Semver range of openvibe-sdk releases it uses."
+ }
+ }
+ }
+ }
+ }
}
}
}
}
}
}
@@ -3298,3 +3298,76 @@ export interface ModManifest {
@@ -3298,3 +3298,76 @@ export interface ModManifest {
};
};
homepage?: string;
homepage?: string;
}
}
+
+/** [email protected] (owner: codes) */
+/**
+ * PROPOSAL (OpenVibe.Codes, roadmap Wave 20): an app release as the platform knows it. The app is a Network developer app (ADR-014): its id is the Network app id, its capabilities are only a request (the grants in Network are the authority), and trust tiers are metadata that never change a grant check. OpenVibe.Codes validates with this schema, loaded into openvibe-contracts' validator, until Contracts publishes it as codes.app-manifest@1.
+ */
+export interface AppManifest {
+ /**
+ * The Network app id (its client_id). Its principal subject is app:<id>.
+ */
+ id: string;
+ name: string;
+ /**
+ * Semantic version of this release.
+ */
+ version: string;
+ description?: string;
+ publisher: SubjectRef;
+ /**
+ * The Network project that owns the app. Tenancy in other services is keyed by it (ADR-014).
+ */
+ project_id: string;
+ /**
+ * The app's environment. Apps never change environment.
+ */
+ environment?: "sandbox" | "production";
+ /**
+ * Capability ids the app asks for (3+ segments). Only active public (or partner, by staff allowance) capabilities can ever be granted to apps.
+ *
+ * @maxItems 64
+ */
+ capabilities: string[];
+ events?: {
+ /**
+ * Event types (or a trailing .* family) the app subscribes to.
+ *
+ * @maxItems 64
+ */
+ consumes?: string[];
+ };
+ /**
+ * Informational copy of the redirect URIs registered in Network (Network's list is the authority).
+ *
+ * @maxItems 10
+ */
+ redirect_uris?:
+ | []
+ | [string]
+ | [string, string]
+ | [string, string, string]
+ | [string, string, string, string]
+ | [string, string, string, string, string]
+ | [string, string, string, string, string, string]
+ | [string, string, string, string, string, string, string]
+ | [string, string, string, string, string, string, string, string]
+ | [string, string, string, string, string, string, string, string, string]
+ | [string, string, string, string, string, string, string, string, string, string];
+ homepage?: string;
+ repository?: string;
+ /**
+ * SPDX license expression.
+ */
+ license?: string;
+ compatibility: {
+ /**
+ * Semver range of openvibe-contracts releases it was built against.
+ */
+ contracts: string;
+ /**
+ * Semver range of openvibe-sdk releases it uses.
+ */
+ sdk?: string;
+ };
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,19 @@
@@ -0,0 +1,19 @@
+{
+ "id": "codes.release.manage",
+ "version": "1.0",
+ "owner": "codes",
+ "status": "active",
+ "visibility": "public",
+ "description": "An app manages release metadata for ITSELF with its own token (audience openvibe.codes): create a release from a validated app or mod manifest, publish, deprecate (with a reason and an optional replacement) and revoke it. The token's sub must be app:<the app in the path>; people manage releases in the portal with their project role instead. Trust tiers are not part of this capability (staff metadata only).",
+ "inputSchema": "codes.app-manifest@1",
+ "permissions": ["codes:releases:write"],
+ "resourceConstraints": ["owner", "project"],
+ "quotaClass": "codes-release-write",
+ "events": ["codes.app.published", "codes.app.deprecated", "codes.app.revoked"],
+ "implementedBy": [
+ "POST /api/v1/apps/:app/releases",
+ "POST /api/v1/releases/:id/publish",
+ "POST /api/v1/releases/:id/deprecate",
+ "POST /api/v1/releases/:id/revoke"
+ ]
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,18 @@
@@ -0,0 +1,18 @@
+{
+ "id": "codes.release.read",
+ "version": "1.0",
+ "owner": "codes",
+ "status": "active",
+ "visibility": "public",
+ "description": "Read public release metadata: an app's published, deprecated and revoked releases with their manifests, compatibility ranges and the app's trust tier (metadata only; it never grants anything). Drafts are never returned. Public; no token needed.",
+ "outputSchema": "codes.app-manifest@1",
+ "permissions": ["codes:releases:read"],
+ "resourceConstraints": ["none"],
+ "quotaClass": "codes-read",
+ "events": [],
+ "implementedBy": [
+ "GET /api/v1/apps/:app/releases",
+ "GET /api/v1/apps/:app/trust",
+ "GET /api/v1/releases/:id"
+ ]
+}
@@ -1,16 +1,30 @@
@@ -1,16 +1,30 @@
{
{
"version": "0.1.0",
"version": "0.1.0",
"contractRanges": {
"contractRanges": {
- "openvibe-contracts": "^0.1.0"
+ "openvibe-contracts": ">=0.26.0 <1.0.0"
},
},
"id": "codes",
"id": "codes",
"name": "OpenVibe.Codes",
"name": "OpenVibe.Codes",
- "status": "placeholder",
+ "status": "alpha",
"repository": "OpenVibers/OpenVibe.Codes",
"repository": "OpenVibers/OpenVibe.Codes",
- "domains": [],
- "capabilities": [],
- "eventsProduced": [],
+ "domains": [
+ "openvibe.codes"
+ ],
+ "publicOrigin": "https://openvibe.codes",
+ "health": "/api/health",
+ "ready": "/api/ready",
+ "capabilities": [
+ "codes.release.read",
+ "codes.release.manage"
+ ],
+ "eventsProduced": [
+ "codes.app.published",
+ "codes.app.deprecated",
+ "codes.app.revoked"
+ ],
"eventsConsumed": [],
"eventsConsumed": [],
- "namespacesOwned": [],
- "notes": "The developer portal: registry and contract explorers, credentials, playgrounds, examples, mod/app publishing, governance. Charter only; no runtime."
+ "namespacesOwned": [
+ "codes.*"
+ ],
+ "notes": "Port 4900, unit openvibe-codes.service, state /var/lib/openvibe-codes. The developer portal (ADR-014): projects, members, apps, credentials, grants and quotas are OWNED BY NETWORK and shown through Network's /api/v1/projects API with the signed-in person's own token; Codes stores none of them and never a secret. Codes owns only manifests, releases (+ append-only release_log), trust tiers (metadata) and playground run logs in its own SQLite. Consumes OpenVibe.Network (SSO with PKCE S256 as OAuth client codes, JWKS, the projects API, the registry, client-credentials) and publishes through OpenVibe.Events (events.event.publish). Playgrounds call Events and Media with the APP's own token only. Docs are generated at boot from the pinned openvibe-contracts and openvibe-sdk."
}
}