Skip to content

Commit 1d953f7

Browse files
authored
Tighten release metadata validation (#29)
1 parent b966c0f commit 1d953f7

File tree

8 files changed

+26
-7
lines changed

8 files changed

+26
-7
lines changed

GOVERNANCE.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,16 @@ Steward duties include:
1515
- preventing schema, example, manifest, checksum, and public-doc drift
1616
- coordinating with Protocol-Commons, Agent Cards, and commandlayer.org mirrors so that current-line path teaching stays coherent
1717

18+
## Succession and continuity
19+
20+
If the founding steward becomes unavailable or chooses to step down, a successor steward may be designated by a signed repository update that:
21+
22+
- names the incoming steward explicitly
23+
- updates this document and any mirrored governance metadata in the same change set
24+
- preserves the rule that published release lines remain immutable
25+
26+
Until such a designation lands, no other party may claim unilateral authority to mutate published artifacts or redefine the current line retroactively.
27+
1828
## Decision rules
1929

2030
| Change type | Requirement |

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,8 @@ sha256sum -c checksums.txt
261261

262262
Agent Cards v1.1.0 should bind directly to the current flat commercial schema URIs published by this repository. They should not point at the historical v1.0.0 `requests/` or `receipts/` paths when declaring current-line commercial capability.
263263

264+
The `manifest.json` alignment metadata is intentionally declarative only. It records the intended version pairing with Protocol-Commons and Agent Cards, but it must not be read as machine-verified cross-repository enforcement on its own.
265+
264266
Protocol-Commons and Protocol-Commercial therefore tell one coherent story:
265267

266268
- Commons defines base actions.

checksums.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ a2a5e61fa04e12786a848e03bbabbc3f9d066ca55a6f48cb1ae1140f6373bf94 examples/v1.1.
2828
9492d90ea14ad35eeb8acd03248ce6061ccdc04a7aff4ed538d8c42be3abc015 examples/v1.1.0/commercial/verify/valid/002-verify.request.valid.json
2929
50874f3eea69a51ac132873b05e39318e4c2241078ca5e258e466934935ec945 examples/v1.1.0/commercial/verify/valid/900-verify.receipt.valid.json
3030
455d19ad1b7ef98e436d8f1c675fee7f2716eb17d301da8d2cc4e2e2c51e624a examples/v1.1.0/commercial/verify/valid/901-verify.receipt.valid.json
31-
0e4a8b868fa2f7d68bd5f65d7687a91ed97cd380b1b979dd7dc15b44a5a28939 manifest.json
31+
a2d3d327da30d33a96e9bc2fa9ccbc3689963c920c136df0e4ba452a7e7284da manifest.json
3232
4d1178e63f6c5a9e1e4d9cc4d386fbad023dd5a85c000ff193285b1fed9af243 schemas/v1.1.0/commercial/authorize/authorize.receipt.schema.json
3333
ef5da55ba5acdd43e8d2715204938762a63819dd370ebc8dfedad014617259c3 schemas/v1.1.0/commercial/authorize/authorize.request.schema.json
3434
66e39d85a503ec2fa096d789b5b3136a451387186fa33424c4bcb07ce9aea49b schemas/v1.1.0/commercial/checkout/checkout.receipt.schema.json
@@ -39,4 +39,4 @@ e9b62cf29d5f58fed922e9bc77c8d3e13e6f7ed04785baad7a7e4fc600ab44b8 schemas/v1.1.0
3939
b876f8ffbfd87e5554374de114414f9e4091ba09c80d07b9b99a40ff1befd7c5 schemas/v1.1.0/commercial/ship/ship.request.schema.json
4040
7abc8e8a2dec058298ba5dd0603f20d9f95f6bc411fcd429fdb3c7a116dcbcca schemas/v1.1.0/commercial/verify/verify.receipt.schema.json
4141
09707b90a6317d10d13f6e5339bc17a7ddc4d5938970ff7e25842876b7f2eea5 schemas/v1.1.0/commercial/verify/verify.request.schema.json
42-
ef4d9050f892c9d4b86382b9fd3018ee8496e6ad26c2fa9a64cbb44b7d549598 schemas/v1.1.0/index.json
42+
0993bbc6dee0ccefa624ef95c47d87398cc3585b0e95f0f6a7e55d4eed176c4f schemas/v1.1.0/index.json

manifest.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
"repository": "https://github.com/commandlayer/protocol-commercial",
88
"homepage": "https://commandlayer.org",
99
"license": "Apache-2.0",
10+
"path_base": ".",
11+
"paths_are_repo_relative": true,
1012
"schemas_root": "schemas/v1.1.0",
1113
"examples_root": "examples/v1.1.0",
1214
"current_index": "schemas/v1.1.0/index.json",
@@ -38,6 +40,7 @@
3840
"protocol_commons": "1.1.0",
3941
"agent_cards": "1.1.0"
4042
},
43+
"alignment_verification": "declarative-only",
4144
"verbs": [
4245
{
4346
"verb": "authorize",

package.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,5 @@
7777
"ajv": "^8.17.1",
7878
"ajv-errors": "^3.0.0",
7979
"ajv-formats": "^3.0.1"
80-
},
81-
"publishConfig": {
82-
"access": "public"
8380
}
8481
}

schemas/v1.1.0/index.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
"name": "@commandlayer/commercial",
33
"version": "1.1.0",
44
"class": "commercial",
5+
"path_base": ".",
6+
"paths_are_repo_relative": true,
57
"schemas_root": "schemas/v1.1.0",
68
"verbs": [
79
{

scripts/validate-all.mjs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,14 @@ async function validateManifest() {
9696
assert(!("$schema" in manifest), "manifest.json must not carry a decorative $schema field");
9797
assert(manifest.version === CURRENT_VERSION, `manifest version must be ${CURRENT_VERSION}`);
9898
assert(manifest.status === "current", "manifest status must be current");
99+
assert(manifest.path_base === ".", "manifest path_base must anchor repo-relative paths");
100+
assert(manifest.paths_are_repo_relative === true, "manifest must declare repo-relative path semantics");
99101
assert(manifest.schemas_root === `schemas/v${CURRENT_VERSION}`, "manifest schemas_root drift");
100102
assert(manifest.examples_root === `examples/v${CURRENT_VERSION}`, "manifest examples_root drift");
101103
assert(manifest.current_index === `schemas/v${CURRENT_VERSION}/index.json`, "manifest current_index drift");
102104
assert(manifest.checksums_file === "checksums.txt", "manifest checksums_file drift");
103105
assert("declared_alignment" in manifest, "manifest must expose declarative alignment metadata");
106+
assert(manifest.alignment_verification === "declarative-only", "manifest alignment verification mode drift");
104107
assert(!("aligns_with" in manifest), "manifest aligns_with field must not imply verified enforcement");
105108
assert(JSON.stringify(manifest.verbs.map((v) => v.verb)) === JSON.stringify(EXPECTED_VERBS), "manifest verb list drift");
106109
}
@@ -171,6 +174,8 @@ async function validateIndex() {
171174
const indexPath = path.join(SCHEMAS_ROOT, "index.json");
172175
const indexJson = await loadJsonStrict(indexPath);
173176
assert(indexJson.version === CURRENT_VERSION, "index.json version drift");
177+
assert(indexJson.path_base === ".", "index.json path_base must anchor repo-relative paths");
178+
assert(indexJson.paths_are_repo_relative === true, "index.json must declare repo-relative path semantics");
174179
assert(indexJson.schemas_root === `schemas/v${CURRENT_VERSION}`, "index.json schemas_root drift");
175180
assert(JSON.stringify(indexJson.verbs) === JSON.stringify(EXPECTED_VERBS.map(expectedVerbEntry)), "index.json verb inventory drift");
176181

scripts/validate-examples.mjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
#!/usr/bin/env node
2-
import { readdir } from "fs/promises";
32
import path from "path";
43
import Ajv2020 from "ajv/dist/2020.js";
54
import addFormats from "ajv-formats";
65
import ajvErrors from "ajv-errors";
76
import { loadJsonStrict } from "./load-json-strict.mjs";
7+
import { readdir } from "fs/promises";
88

99
const ROOT_DIR = process.cwd();
1010
const CURRENT_VERSION = "1.1.0";
@@ -24,7 +24,7 @@ async function validateVerb(verb) {
2424

2525
for (const group of ["valid", "invalid"]) {
2626
const dir = path.join(EXAMPLES_ROOT, verb, group);
27-
const files = (await fs.readdir(dir)).filter((file) => file.endsWith(".json")).sort();
27+
const files = (await readdir(dir)).filter((file) => file.endsWith(".json")).sort();
2828
const requestFiles = files.filter((file) => file.includes("request"));
2929
const receiptFiles = files.filter((file) => file.includes("receipt"));
3030
if (requestFiles.length === 0 || receiptFiles.length === 0) {

0 commit comments

Comments
 (0)