graceful-boundaries 1.5.0 → 1.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONFORMANCE.md +1 -1
- package/README.md +6 -4
- package/evals/check.js +22 -3
- package/package.json +1 -1
- package/schema/limits.schema.json +4 -1
- package/schema/refusal-429.schema.json +1 -1
- package/schema/refusal.schema.json +4 -1
- package/spec.md +2 -2
package/CONFORMANCE.md
CHANGED
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ A specification for how services communicate their operational limits to humans
|
|
|
5
5
|
**[gracefulboundaries.dev](https://gracefulboundaries.dev)**
|
|
6
6
|
|
|
7
7
|
[](https://creativecommons.org/licenses/by/4.0/)
|
|
8
|
-
[](CHANGELOG.md)
|
|
9
9
|
[](https://github.com/snapsynapse/graceful-boundaries/actions)
|
|
10
10
|
[](https://clawhub.ai/snapsynapse/graceful-boundaries)
|
|
11
11
|
|
|
@@ -141,7 +141,7 @@ npx graceful-boundaries check https://your-service.com --check-cloaking
|
|
|
141
141
|
|
|
142
142
|

|
|
143
143
|
|
|
144
|
-
Or clone and run from the project root with `node evals/check.js <url>`. Run the unit test suite (
|
|
144
|
+
Or clone and run from the project root with `node evals/check.js <url>`. Run the unit test suite (259 tests, no dependencies):
|
|
145
145
|
|
|
146
146
|
```bash
|
|
147
147
|
npm test
|
|
@@ -190,7 +190,7 @@ The shortest path from "read the spec" to "conformant service":
|
|
|
190
190
|
|
|
191
191
|
1. **Copy a middleware example** -- dependency-free Level 2 implementations (Level 4 with one flag) for [Express, FastAPI, Cloudflare Workers, and Hono](examples/middleware/).
|
|
192
192
|
2. **Copy the nearest limits.json** -- complete discovery responses for a [SaaS API, free scanner, LLM API, and content site](examples/limits/).
|
|
193
|
-
3. **Validate your
|
|
193
|
+
3. **Validate your body shapes** -- published [JSON Schemas](schema/) for refusals, 429s, and the discovery endpoint, served at `https://gracefulboundaries.dev/schema/`. Importable into OpenAPI and CI validators; run the checker for origin-aware SC-6 URL safety and conformance.
|
|
194
194
|
4. **Verify** -- `npx graceful-boundaries check https://your-service.example`, then gate it in CI with the GitHub Action above.
|
|
195
195
|
5. **Declare** -- add yourself to [ADOPTERS.md](ADOPTERS.md) and embed a [conformance badge](ADOPTERS.md#badges).
|
|
196
196
|
|
|
@@ -239,6 +239,8 @@ npx graceful-boundaries check https://siteline.to
|
|
|
239
239
|
|
|
240
240
|
Services implementing the spec are listed in [ADOPTERS.md](ADOPTERS.md), which also covers how to add yours and embed a conformance badge.
|
|
241
241
|
|
|
242
|
+
The [adoption validation plan](docs/adoption-validation.md) defines the evidence required before deferred fields or extensions are promoted. Registered services are rechecked weekly, with point-in-time JSON results retained as workflow artifacts rather than presented as certification.
|
|
243
|
+
|
|
242
244
|
## Security
|
|
243
245
|
|
|
244
246
|
The specification includes a [threat model and security audit](SECURITY-AUDIT.md) covering rate limit calibration attacks, security posture disclosure, validation oracles, content cloaking via agent-signaling headers, action boundary risks, untrusted machine-readable guidance, and other considerations (SC-1 through SC-16), all addressed in the spec.
|
|
@@ -249,7 +251,7 @@ Graceful Boundaries is free and open. If your team relies on this spec, consider
|
|
|
249
251
|
|
|
250
252
|
## License
|
|
251
253
|
|
|
252
|
-
CC-BY-4.0.
|
|
254
|
+
The specification and documentation are CC-BY-4.0. The checker and reference code are MIT licensed. See [LICENSE-SPEC](LICENSE-SPEC) and [LICENSE](LICENSE).
|
|
253
255
|
|
|
254
256
|
## About
|
|
255
257
|
|
package/evals/check.js
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
* node evals/check.js https://your-service.com --limits-path /api/limits
|
|
17
17
|
* node evals/check.js https://your-service.com --json
|
|
18
18
|
* node evals/check.js https://your-service.com --check-cloaking
|
|
19
|
+
* node evals/check.js https://your-service.com --min-level 2
|
|
19
20
|
*/
|
|
20
21
|
|
|
21
22
|
const REQUIRED_REFUSAL_FIELDS = ["error", "detail", "limit", "retryAfterSeconds", "why"];
|
|
@@ -33,14 +34,27 @@ const OPTIONAL_LIMIT_NUMBER_FIELDS = [
|
|
|
33
34
|
|
|
34
35
|
function parseArgs(argv) {
|
|
35
36
|
const args = argv.slice(2);
|
|
36
|
-
const options = {
|
|
37
|
+
const options = {
|
|
38
|
+
baseUrl: null,
|
|
39
|
+
limitsPath: null,
|
|
40
|
+
json: false,
|
|
41
|
+
checkCloaking: false,
|
|
42
|
+
minLevel: null,
|
|
43
|
+
errors: [],
|
|
44
|
+
};
|
|
37
45
|
|
|
38
46
|
for (let i = 0; i < args.length; i++) {
|
|
39
47
|
if (args[i] === "--limits-path" && i + 1 < args.length) {
|
|
40
48
|
options.limitsPath = args[++i];
|
|
41
49
|
} else if (args[i] === "--min-level" && i + 1 < args.length) {
|
|
42
|
-
const
|
|
43
|
-
|
|
50
|
+
const raw = args[++i];
|
|
51
|
+
if (!/^[0-4]$/.test(raw)) {
|
|
52
|
+
options.errors.push(`--min-level must be an integer from 0 to 4, got "${raw}"`);
|
|
53
|
+
} else {
|
|
54
|
+
options.minLevel = Number(raw);
|
|
55
|
+
}
|
|
56
|
+
} else if (args[i] === "--min-level") {
|
|
57
|
+
options.errors.push("--min-level requires a value from 0 to 4");
|
|
44
58
|
} else if (args[i] === "--json") {
|
|
45
59
|
options.json = true;
|
|
46
60
|
} else if (args[i] === "--check-cloaking") {
|
|
@@ -933,6 +947,11 @@ function assessLevel(limitsResults, refusalCheck, proactiveHeaders) {
|
|
|
933
947
|
async function main() {
|
|
934
948
|
const options = parseArgs(process.argv);
|
|
935
949
|
|
|
950
|
+
if (options.errors.length > 0) {
|
|
951
|
+
for (const error of options.errors) console.error(error);
|
|
952
|
+
process.exit(1);
|
|
953
|
+
}
|
|
954
|
+
|
|
936
955
|
if (!options.baseUrl) {
|
|
937
956
|
console.error("Usage: node evals/check.js <base-url> [--limits-path /path] [--json] [--check-cloaking] [--min-level N]");
|
|
938
957
|
console.error("");
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://gracefulboundaries.dev/schema/limits.schema.json",
|
|
4
4
|
"title": "Graceful Boundaries limits discovery response",
|
|
5
|
-
"description": "Response shape for the limits discovery endpoint (GET /api/limits or GET /.well-known/limits) per Graceful Boundaries. Spec: https://gracefulboundaries.dev/spec",
|
|
5
|
+
"description": "Response shape for the limits discovery endpoint (GET /api/limits or GET /.well-known/limits) per Graceful Boundaries. Spec: https://gracefulboundaries.dev/spec.md",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"required": ["service", "description", "limits"],
|
|
8
8
|
"properties": {
|
|
@@ -23,15 +23,18 @@
|
|
|
23
23
|
},
|
|
24
24
|
"changelog": {
|
|
25
25
|
"type": "string",
|
|
26
|
+
"$comment": "SC-6 same-origin/relative URL safety is origin-dependent and cannot be fully enforced by this standalone schema. Use evals/check.js or equivalent origin-aware validation.",
|
|
26
27
|
"description": "URL to a changelog resource for limit changes. Must be a relative path or same-origin absolute URL."
|
|
27
28
|
},
|
|
28
29
|
"feed": {
|
|
29
30
|
"type": "string",
|
|
31
|
+
"$comment": "SC-6 same-origin/relative URL safety is origin-dependent and cannot be fully enforced by this standalone schema. Use evals/check.js or equivalent origin-aware validation.",
|
|
30
32
|
"description": "URL to a feed (JSON Feed, Atom, RSS) for change notifications. Must be a relative path or same-origin absolute URL."
|
|
31
33
|
},
|
|
32
34
|
"extensions": {
|
|
33
35
|
"type": "object",
|
|
34
36
|
"additionalProperties": { "type": "string" },
|
|
37
|
+
"$comment": "SC-6 same-origin/relative URL safety for extension URLs is origin-dependent and cannot be fully enforced by this standalone schema. Use evals/check.js or equivalent origin-aware validation.",
|
|
35
38
|
"description": "Named extension discovery URLs (e.g. actionBoundaries). Each value must be a relative path or same-origin absolute URL. Presence does not affect Level 1-4 conformance."
|
|
36
39
|
},
|
|
37
40
|
"limits": {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://gracefulboundaries.dev/schema/refusal-429.schema.json",
|
|
4
4
|
"title": "Graceful Boundaries 429 refusal response",
|
|
5
|
-
"description": "Structured refusal shape for limit-class responses (429). Extends the core refusal shape with the fields Level 1 requires on rate-limit refusals. Spec: https://gracefulboundaries.dev/spec",
|
|
5
|
+
"description": "Structured refusal shape for limit-class responses (429). Extends the core refusal shape with the fields Level 1 requires on rate-limit refusals. Spec: https://gracefulboundaries.dev/spec.md",
|
|
6
6
|
"$ref": "https://gracefulboundaries.dev/schema/refusal.schema.json",
|
|
7
7
|
"required": ["error", "detail", "why", "limit", "retryAfterSeconds"]
|
|
8
8
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://gracefulboundaries.dev/schema/refusal.schema.json",
|
|
4
4
|
"title": "Graceful Boundaries non-success response",
|
|
5
|
-
"description": "Core structured refusal shape for all non-success HTTP responses (400, 401, 403, 404, 405, 410, 422, 429, 500, 502, 503, 504) per Graceful Boundaries. Spec: https://gracefulboundaries.dev/spec",
|
|
5
|
+
"description": "Core structured refusal shape for all non-success HTTP responses (400, 401, 403, 404, 405, 410, 422, 429, 500, 502, 503, 504) per Graceful Boundaries. Spec: https://gracefulboundaries.dev/spec.md",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"required": ["error", "detail", "why"],
|
|
8
8
|
"properties": {
|
|
@@ -52,10 +52,12 @@
|
|
|
52
52
|
},
|
|
53
53
|
"cachedResultUrl": {
|
|
54
54
|
"type": "string",
|
|
55
|
+
"$comment": "SC-6 same-origin/relative URL safety is origin-dependent and cannot be fully enforced by this standalone schema. Use evals/check.js or equivalent origin-aware validation.",
|
|
55
56
|
"description": "URL to retrieve the cached result. Must be a relative path or same-origin absolute URL (SC-6)."
|
|
56
57
|
},
|
|
57
58
|
"alternativeEndpoint": {
|
|
58
59
|
"type": "string",
|
|
60
|
+
"$comment": "SC-6 same-origin/relative URL safety is origin-dependent and cannot be fully enforced by this standalone schema. Use evals/check.js or equivalent origin-aware validation.",
|
|
59
61
|
"description": "A different endpoint that may serve the need. Must be a relative path or same-origin absolute URL (SC-6)."
|
|
60
62
|
},
|
|
61
63
|
"upgradeUrl": {
|
|
@@ -89,6 +91,7 @@
|
|
|
89
91
|
},
|
|
90
92
|
"scanUrl": {
|
|
91
93
|
"type": "string",
|
|
94
|
+
"$comment": "SC-6 same-origin/relative URL safety is origin-dependent and cannot be fully enforced by this standalone schema. Use evals/check.js or equivalent origin-aware validation.",
|
|
92
95
|
"description": "Endpoint to create the missing resource. Not a trust bypass (SC-8)."
|
|
93
96
|
},
|
|
94
97
|
"statusUrl": {
|
package/spec.md
CHANGED