Skip to content
Merged
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
2 changes: 2 additions & 0 deletions docs/plugin-authoring.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ the native Convax file picker; a Pet surface never receives a filesystem path.
Convax accepts one current-format transparent 1536×1872 PNG or WebP atlas, stores a
managed copy, and serves it through `convax-pet-asset:`. Legacy Goku folders,
`pet.json`, remote assets, and arbitrary file reads are not supported.
Pet Plugins that do not offer custom collection management omit this optional
grant while retaining the three required activity and preference capabilities.

The settings and overlay pages run with no Node, Electron, remote network, native
path, or arbitrary IPC access. Their surface-scoped `convax.pet-host/1` ports expose
Expand Down
7 changes: 4 additions & 3 deletions docs/registry-spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,10 @@ One Pet feature Plugin is a `convax.plugin/5` capability published through the
normal Plugin Registry item. Its complete embedded manifest contains
`contributes.pet` with package-relative `library`, `overlay`, and `settings` paths
plus `protocol: "convax.pet-host/1"`. It requests exactly `pet.activity.read`,
`pet.activity.open`, `pet.preferences.write`, and `pet.custom.manage`, and has no
runtime or companion executable. The `convax.plugin-capability/1` compatibility
label remains the transport-neutral admission contract.
`pet.activity.open`, and `pet.preferences.write`, may additionally request the
exact `pet.custom.manage` grant, and has no runtime or companion executable.
Convax Pet 0.2.2 requests all four. The `convax.plugin-capability/1`
compatibility label remains the transport-neutral admission contract.

Clients validate both static surface entries, the strict `convax.pet-library/1`
document, and every referenced atlas before activation. Installation does not
Expand Down
2 changes: 1 addition & 1 deletion registry/config.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"sequence": 31,
"sequence": 32,
"yanked": []
}
13 changes: 10 additions & 3 deletions schemas/convax-plugin-manifest-v5.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -151,13 +151,20 @@
"required": ["capabilities"],
"properties": {
"capabilities": {
"minItems": 4,
"minItems": 3,
"maxItems": 4,
"items": {
"enum": [
"pet.activity.read",
"pet.activity.open",
"pet.preferences.write",
"pet.custom.manage"
]
},
"allOf": [
{ "contains": { "const": "pet.activity.read" } },
{ "contains": { "const": "pet.activity.open" } },
{ "contains": { "const": "pet.preferences.write" } },
{ "contains": { "const": "pet.custom.manage" } }
{ "contains": { "const": "pet.preferences.write" } }
]
}
},
Expand Down
16 changes: 7 additions & 9 deletions tooling/lib.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -800,15 +800,13 @@ function parsePluginManifestV5(value, label) {
? undefined
: parsePetV5(value.contributes.pet, `${label} pet`)
if (pet !== undefined) {
const requiredPetCapabilities = [
"pet.activity.read",
"pet.activity.open",
"pet.preferences.write",
"pet.custom.manage",
]
if (capabilities.length !== requiredPetCapabilities.length ||
requiredPetCapabilities.some((capability) => !capabilities.includes(capability))) {
error(label, "pet capabilities must be exactly pet.activity.read, pet.activity.open, pet.preferences.write, and pet.custom.manage")
const requiredPetCapabilities = ["pet.activity.read", "pet.activity.open", "pet.preferences.write"]
const allowedPetCapabilities = new Set([...requiredPetCapabilities, "pet.custom.manage"])
if (capabilities.length < requiredPetCapabilities.length ||
capabilities.length > allowedPetCapabilities.size ||
requiredPetCapabilities.some((capability) => !capabilities.includes(capability)) ||
capabilities.some((capability) => !allowedPetCapabilities.has(capability))) {
error(label, "pet capabilities must be exactly pet.activity.read, pet.activity.open, and pet.preferences.write, with optional pet.custom.manage")
}
if (hasRuntime) error(label, "pet feature cannot declare an executable runtime")
}
Expand Down
19 changes: 19 additions & 0 deletions tooling/plugin-v5.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,12 @@ describe("convax.plugin/5 transport-neutral and pet contributions", () => {

test("requires the exact pet capabilities and forbids executable runtimes", () => {
expect(() => parsePluginManifest({ ...petManifest(), capabilities: [] })).toThrow("pet capabilities")
expect(() =>
parsePluginManifest({
...petManifest(),
capabilities: [...petManifest().capabilities, "projects.read"],
}),
).toThrow("pet capabilities")
expect(() =>
parsePluginManifest({
...petManifest(),
Expand All @@ -202,6 +208,19 @@ describe("convax.plugin/5 transport-neutral and pet contributions", () => {
).toThrow("pet feature")
})

test("keeps historical Pet manifests valid when custom management is absent", () => {
const historical = petManifest({
version: "0.2.1",
capabilities: petManifest().capabilities.filter((capability) => capability !== "pet.custom.manage"),
})

expect(parsePluginManifest(historical).capabilities).toEqual([
"pet.activity.read",
"pet.activity.open",
"pet.preferences.write",
])
})

test("validates every packaged pet library atlas", () => {
const manifest = parsePluginManifest(petManifest())
const comet = {
Expand Down