feat: 기능 추가 과정중
This commit is contained in:
+32
-8
@@ -83,6 +83,9 @@
|
||||
{ "script": "check:types:fixture:ts-result", "expect": "fail" },
|
||||
{ "script": "check:types:fixture:application-output", "expect": "fail" },
|
||||
{ "script": "check:types:fixture:application-input", "expect": "fail" },
|
||||
{ "script": "check:types:fixture:feature-input", "expect": "fail" },
|
||||
{ "script": "check:types:fixture:failure-kind", "expect": "fail" },
|
||||
{ "script": "check:types:fixture:reference-operation", "expect": "fail" },
|
||||
{ "script": "check:types:fixture:async-overlay", "expect": "fail" },
|
||||
{ "script": "check:types:fixture:route-runtime", "expect": "fail" },
|
||||
{ "script": "check:types:fixture:page-action", "expect": "fail" },
|
||||
@@ -145,6 +148,11 @@
|
||||
"name": "e2e",
|
||||
"steps": [
|
||||
{ "script": "test:e2e", "expect": "pass" },
|
||||
{ "script": "test:browser-capabilities", "expect": "pass" },
|
||||
{
|
||||
"script": "verify:browser-capability-evidence",
|
||||
"expect": "pass"
|
||||
},
|
||||
{ "script": "test:storybook", "expect": "pass" },
|
||||
{ "script": "test:visual", "expect": "pass" },
|
||||
{ "script": "check:test-evidence", "expect": "pass" },
|
||||
@@ -154,6 +162,8 @@
|
||||
"evidence": [
|
||||
"artifacts/tests/e2e/report/index.html",
|
||||
"artifacts/tests/e2e/results.xml",
|
||||
"artifacts/tests/browser-capabilities/report/index.html",
|
||||
"artifacts/tests/browser-capabilities/results.xml",
|
||||
"artifacts/tests/storybook/report/index.html",
|
||||
"artifacts/tests/storybook/results.xml",
|
||||
"artifacts/tests/visual/report/index.html",
|
||||
@@ -192,6 +202,9 @@
|
||||
{ "script": "check:i18n:fixture", "expect": "fail" },
|
||||
{ "script": "check:diagnostics", "expect": "pass" },
|
||||
{ "script": "check:diagnostics:fixture", "expect": "fail" },
|
||||
{ "script": "check:browser-file-storage-boundaries", "expect": "pass" },
|
||||
{ "script": "check:realtime-boundaries", "expect": "pass" },
|
||||
{ "script": "check:realtime-boundaries:fixture", "expect": "pass" },
|
||||
{ "script": "check:optional-recipes:source", "expect": "pass" },
|
||||
{ "script": "check:optional-recipe-fixtures", "expect": "pass" },
|
||||
{ "script": "check:registries", "expect": "pass" },
|
||||
@@ -212,6 +225,7 @@
|
||||
"artifacts/quality/i18n-fixture.json",
|
||||
"artifacts/quality/diagnostics.json",
|
||||
"artifacts/quality/diagnostics-fixture.json",
|
||||
"artifacts/quality/realtime-boundaries.json",
|
||||
"artifacts/quality/optional-recipes.json",
|
||||
"artifacts/quality/optional-recipe-fixtures.json",
|
||||
"artifacts/quality/registries.json",
|
||||
@@ -315,7 +329,7 @@
|
||||
],
|
||||
"logPath": "artifacts/quality/gates/FE-GATE-016.txt",
|
||||
"evidence": [
|
||||
"artifacts/runbooks/FE-RB-005/local-release/record.json"
|
||||
"artifacts/runbooks/FE-RB-005/record.json"
|
||||
],
|
||||
"retentionClass": "prod-drill"
|
||||
},
|
||||
@@ -354,12 +368,22 @@
|
||||
"name": "removability",
|
||||
"steps": [
|
||||
{ "script": "test:sample-removal", "expect": "pass" },
|
||||
{ "script": "test:optional-recipe-removal", "expect": "pass" }
|
||||
{ "script": "test:optional-recipe-removal", "expect": "pass" },
|
||||
{
|
||||
"script": "test:browser-file-storage-removal",
|
||||
"expect": "pass"
|
||||
},
|
||||
{
|
||||
"script": "test:realtime-removal",
|
||||
"expect": "pass"
|
||||
}
|
||||
],
|
||||
"logPath": "artifacts/quality/gates/FE-GATE-020.txt",
|
||||
"evidence": [
|
||||
"artifacts/tests/sample-removal.xml",
|
||||
"artifacts/tests/optional-recipe-removal.xml"
|
||||
"artifacts/tests/optional-recipe-removal.xml",
|
||||
"artifacts/tests/browser-file-storage-runtime-removal.xml",
|
||||
"artifacts/tests/realtime-runtime-removal.xml"
|
||||
],
|
||||
"retentionClass": "merge-cycle"
|
||||
},
|
||||
@@ -375,7 +399,7 @@
|
||||
],
|
||||
"logPath": "artifacts/quality/gates/FE-GATE-021.txt",
|
||||
"evidence": [
|
||||
"artifacts/runbooks/FE-RB-001/local-release/record.json"
|
||||
"artifacts/runbooks/FE-RB-001/record.json"
|
||||
],
|
||||
"retentionClass": "prod-drill"
|
||||
},
|
||||
@@ -391,7 +415,7 @@
|
||||
],
|
||||
"logPath": "artifacts/quality/gates/FE-GATE-022.txt",
|
||||
"evidence": [
|
||||
"artifacts/runbooks/FE-RB-002/local-release/record.json"
|
||||
"artifacts/runbooks/FE-RB-002/record.json"
|
||||
],
|
||||
"retentionClass": "prod-drill"
|
||||
},
|
||||
@@ -407,7 +431,7 @@
|
||||
],
|
||||
"logPath": "artifacts/quality/gates/FE-GATE-023.txt",
|
||||
"evidence": [
|
||||
"artifacts/runbooks/FE-RB-003/local-release/record.json"
|
||||
"artifacts/runbooks/FE-RB-003/record.json"
|
||||
],
|
||||
"retentionClass": "prod-drill"
|
||||
},
|
||||
@@ -423,7 +447,7 @@
|
||||
],
|
||||
"logPath": "artifacts/quality/gates/FE-GATE-024.txt",
|
||||
"evidence": [
|
||||
"artifacts/runbooks/FE-RB-004/local-release/record.json"
|
||||
"artifacts/runbooks/FE-RB-004/record.json"
|
||||
],
|
||||
"retentionClass": "prod-drill"
|
||||
},
|
||||
@@ -439,7 +463,7 @@
|
||||
],
|
||||
"logPath": "artifacts/quality/gates/FE-GATE-025.txt",
|
||||
"evidence": [
|
||||
"artifacts/runbooks/FE-RB-005/local-release/record.json"
|
||||
"artifacts/runbooks/FE-RB-005/record.json"
|
||||
],
|
||||
"retentionClass": "prod-drill"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"snapshotDigest": "e8448e46bc65326e9b2eb23cdce0870242faedb7a354942389c4a95b0e392d90",
|
||||
"snapshotDigest": "67f1ad2bf35d04470a7fba1a5ae8f98608b5d70b70887e383692b1e2d6127752",
|
||||
"owner": "frontend-platform",
|
||||
"reason": "RP-10 initial approved executable registry baseline",
|
||||
"approvedAt": "2026-07-26T07:53:45.969Z"
|
||||
"reason": "Typed Web Storage codecs and query invalidation topic protocol",
|
||||
"approvedAt": "2026-07-27T16:41:15.888Z"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
{
|
||||
"registryId": "FE-REG-ROUTE",
|
||||
"owner": "feature-frontend-routing-release-recovery-runtime",
|
||||
"source": "src/features/installed-feature-contracts.js",
|
||||
"source": "src/features/installed-feature-contracts.ts",
|
||||
"rowCount": 9,
|
||||
"contract": {
|
||||
"requiredFields": [
|
||||
@@ -218,7 +218,7 @@
|
||||
{
|
||||
"registryId": "FE-REG-ROUTE-RUNTIME",
|
||||
"owner": "feature-frontend-routing-release-recovery-runtime",
|
||||
"source": "src/features/installed-feature-contracts.js",
|
||||
"source": "src/features/installed-feature-contracts.ts",
|
||||
"rowCount": 9,
|
||||
"contract": {
|
||||
"requiredFields": [
|
||||
@@ -323,7 +323,7 @@
|
||||
{
|
||||
"registryId": "FE-REG-API",
|
||||
"owner": "feature-frontend-api-client-response-envelope-contract",
|
||||
"source": "src/features/installed-feature-contracts.js",
|
||||
"source": "src/features/installed-feature-contracts.ts",
|
||||
"rowCount": 3,
|
||||
"contract": {
|
||||
"requiredFields": [
|
||||
@@ -451,7 +451,7 @@
|
||||
{
|
||||
"registryId": "FE-REG-SCHEMA",
|
||||
"owner": "feature-frontend-contract-schema-registry",
|
||||
"source": "src/features/installed-feature-contracts.js",
|
||||
"source": "src/features/installed-feature-contracts.ts",
|
||||
"rowCount": 8,
|
||||
"contract": {
|
||||
"requiredFields": [
|
||||
@@ -543,7 +543,7 @@
|
||||
{
|
||||
"registryId": "FE-REG-ENV",
|
||||
"owner": "feature-frontend-env-runtime-config-contract",
|
||||
"source": "src/contracts/env.js",
|
||||
"source": "src/contracts/env.ts",
|
||||
"rowCount": 14,
|
||||
"contract": {
|
||||
"requiredFields": [
|
||||
@@ -669,7 +669,7 @@
|
||||
{
|
||||
"registryId": "FE-REG-STORAGE",
|
||||
"owner": "feature-frontend-storage-registry-contract",
|
||||
"source": "src/contracts/storage-keys.js",
|
||||
"source": "src/contracts/storage-keys.ts",
|
||||
"rowCount": 4,
|
||||
"contract": {
|
||||
"requiredFields": [
|
||||
@@ -678,6 +678,7 @@
|
||||
"backend",
|
||||
"classification",
|
||||
"schemaVersion",
|
||||
"valueCodec",
|
||||
"ttl",
|
||||
"migration",
|
||||
"quotaFallback"
|
||||
@@ -688,8 +689,9 @@
|
||||
"backend": "string",
|
||||
"classification": "string",
|
||||
"schemaVersion": "integer",
|
||||
"valueCodec": "string",
|
||||
"ttl": "integer|string|null",
|
||||
"migration": "string|function",
|
||||
"migration": "string",
|
||||
"quotaFallback": "string"
|
||||
},
|
||||
"uniqueFields": [
|
||||
@@ -701,7 +703,6 @@
|
||||
"memory",
|
||||
"sessionStorage",
|
||||
"localStorage",
|
||||
"indexedDB",
|
||||
"disabled",
|
||||
"forbidden"
|
||||
],
|
||||
@@ -710,6 +711,14 @@
|
||||
"opaque-cache",
|
||||
"sensitive-forbidden"
|
||||
],
|
||||
"valueCodec": [
|
||||
"color-scheme-v1",
|
||||
"opaque-string-v1",
|
||||
"none"
|
||||
],
|
||||
"migration": [
|
||||
"discard"
|
||||
],
|
||||
"quotaFallback": [
|
||||
"memory",
|
||||
"no-persist",
|
||||
@@ -724,6 +733,7 @@
|
||||
"backend",
|
||||
"classification",
|
||||
"schemaVersion",
|
||||
"valueCodec",
|
||||
"migration"
|
||||
]
|
||||
},
|
||||
@@ -738,7 +748,8 @@
|
||||
"quotaFallback": "feature-disable",
|
||||
"schemaVersion": 1,
|
||||
"scope": "auth",
|
||||
"ttl": null
|
||||
"ttl": null,
|
||||
"valueCodec": "none"
|
||||
},
|
||||
"CHUNK_RELOAD_GUARD": {
|
||||
"backend": "sessionStorage",
|
||||
@@ -750,7 +761,8 @@
|
||||
"quotaFallback": "no-persist",
|
||||
"schemaVersion": 1,
|
||||
"scope": "release",
|
||||
"ttl": "session"
|
||||
"ttl": "session",
|
||||
"valueCodec": "opaque-string-v1"
|
||||
},
|
||||
"COLOR_SCHEME": {
|
||||
"backend": "localStorage",
|
||||
@@ -762,7 +774,8 @@
|
||||
"quotaFallback": "memory",
|
||||
"schemaVersion": 1,
|
||||
"scope": "preference",
|
||||
"ttl": null
|
||||
"ttl": null,
|
||||
"valueCodec": "color-scheme-v1"
|
||||
},
|
||||
"QUERY_PERSISTENCE": {
|
||||
"backend": "disabled",
|
||||
@@ -774,14 +787,15 @@
|
||||
"quotaFallback": "feature-disable",
|
||||
"schemaVersion": 1,
|
||||
"scope": "cache",
|
||||
"ttl": null
|
||||
"ttl": null,
|
||||
"valueCodec": "none"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"registryId": "FE-REG-ERROR",
|
||||
"owner": "feature-frontend-error-classification-boundary-contract",
|
||||
"source": "src/contracts/errors.js",
|
||||
"source": "src/contracts/errors.ts",
|
||||
"rowCount": 31,
|
||||
"contract": {
|
||||
"requiredFields": [
|
||||
@@ -1393,7 +1407,7 @@
|
||||
{
|
||||
"registryId": "FE-REG-QUERY",
|
||||
"owner": "feature-frontend-server-state-caching-contract",
|
||||
"source": "src/features/installed-feature-contracts.js",
|
||||
"source": "src/features/installed-feature-contracts.ts",
|
||||
"rowCount": 1,
|
||||
"contract": {
|
||||
"requiredFields": [
|
||||
@@ -1401,6 +1415,8 @@
|
||||
"serialization",
|
||||
"identity",
|
||||
"invalidation",
|
||||
"invalidationTopic",
|
||||
"crossContext",
|
||||
"version",
|
||||
"persistence"
|
||||
],
|
||||
@@ -1409,13 +1425,19 @@
|
||||
"serialization": "string",
|
||||
"identity": "string",
|
||||
"invalidation": "string",
|
||||
"invalidationTopic": "string",
|
||||
"crossContext": "string",
|
||||
"version": "integer",
|
||||
"persistence": "string"
|
||||
},
|
||||
"uniqueFields": [
|
||||
"namespace"
|
||||
"namespace",
|
||||
"invalidationTopic"
|
||||
],
|
||||
"allowedValues": {
|
||||
"crossContext": [
|
||||
"invalidate-only"
|
||||
],
|
||||
"persistence": [
|
||||
"disabled"
|
||||
]
|
||||
@@ -1426,14 +1448,18 @@
|
||||
"namespace",
|
||||
"serialization",
|
||||
"identity",
|
||||
"invalidationTopic",
|
||||
"crossContext",
|
||||
"version",
|
||||
"persistence"
|
||||
]
|
||||
},
|
||||
"rows": {
|
||||
"REFERENCE_RESOURCE": {
|
||||
"crossContext": "invalidate-only",
|
||||
"identity": "no-pii-token-or-raw-url",
|
||||
"invalidation": "reference resource namespace after successful mutation",
|
||||
"invalidationTopic": "qinv.01k10f7m3w9p6r2c8v5n4x",
|
||||
"namespace": [
|
||||
"reference-resource",
|
||||
1
|
||||
@@ -1447,7 +1473,7 @@
|
||||
{
|
||||
"registryId": "FE-REG-TELEMETRY",
|
||||
"owner": "feature-frontend-diagnostics-telemetry-runtime",
|
||||
"source": "src/contracts/telemetry.js",
|
||||
"source": "src/contracts/telemetry.ts",
|
||||
"rowCount": 5,
|
||||
"contract": {
|
||||
"requiredFields": [
|
||||
@@ -1629,7 +1655,7 @@
|
||||
{
|
||||
"registryId": "FE-REG-RELEASE",
|
||||
"owner": "feature-frontend-release-cache-rollback-contract",
|
||||
"source": "src/contracts/release-tokens.js",
|
||||
"source": "src/contracts/release-tokens.ts",
|
||||
"rowCount": 8,
|
||||
"contract": {
|
||||
"requiredFields": [
|
||||
|
||||
@@ -1,4 +1,77 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"changes": []
|
||||
"changes": [
|
||||
{
|
||||
"changeId": "FE-REG-QUERY:$contract:allowedValues:contract-field-changed",
|
||||
"versionBump": "Cross-context invalidation wire protocol starts at version 1.",
|
||||
"migration": "Every installed query row declares invalidate-only; older tabs remain local-only.",
|
||||
"compatibilityWindow": "Mixed releases are isolated by release cacheEpoch and never exchange query keys or values.",
|
||||
"rollback": "Remove the coordinator composition and the two query registry fields.",
|
||||
"owner": "frontend-platform"
|
||||
},
|
||||
{
|
||||
"changeId": "FE-REG-QUERY:$contract:breakingFields:contract-field-changed",
|
||||
"versionBump": "Cross-context invalidation wire protocol starts at version 1.",
|
||||
"migration": "Every installed query row declares its opaque topic and transport policy.",
|
||||
"compatibilityWindow": "A release cacheEpoch rejects messages from a different deployed contract.",
|
||||
"rollback": "Remove the coordinator composition and restore the prior query registry contract.",
|
||||
"owner": "frontend-platform"
|
||||
},
|
||||
{
|
||||
"changeId": "FE-REG-QUERY:$contract:fieldTypes:contract-field-changed",
|
||||
"versionBump": "Cross-context invalidation wire protocol starts at version 1.",
|
||||
"migration": "The installed reference query row and all consumers were updated atomically.",
|
||||
"compatibilityWindow": "Old clients do not consume the new fields; new clients validate them before boot.",
|
||||
"rollback": "Restore the previous query registry field types and local-only invalidation.",
|
||||
"owner": "frontend-platform"
|
||||
},
|
||||
{
|
||||
"changeId": "FE-REG-QUERY:$contract:requiredFields:contract-field-changed",
|
||||
"versionBump": "Cross-context invalidation wire protocol starts at version 1.",
|
||||
"migration": "Missing topics now fail registry validation instead of silently degrading at runtime.",
|
||||
"compatibilityWindow": "Only a fully built release consumes its own installed registry snapshot.",
|
||||
"rollback": "Remove the newly required fields and cross-context composition together.",
|
||||
"owner": "frontend-platform"
|
||||
},
|
||||
{
|
||||
"changeId": "FE-REG-QUERY:$contract:uniqueFields:contract-field-changed",
|
||||
"versionBump": "Cross-context invalidation wire protocol starts at version 1.",
|
||||
"migration": "Existing query namespaces received unique registry-issued opaque topics.",
|
||||
"compatibilityWindow": "Topics are scoped by release cacheEpoch, so mixed releases cannot collide.",
|
||||
"rollback": "Drop invalidationTopic uniqueness after removing the transport consumer.",
|
||||
"owner": "frontend-platform"
|
||||
},
|
||||
{
|
||||
"changeId": "FE-REG-STORAGE:$contract:allowedValues:contract-field-changed",
|
||||
"versionBump": "Web Storage value codec contracts start at version 1.",
|
||||
"migration": "Existing keys retain their physical schema version; values outside the selected codec are discarded.",
|
||||
"compatibilityWindow": "Valid existing color-scheme and opaque-string records remain readable.",
|
||||
"rollback": "Restore the previous registry contract; no physical key deletion is required.",
|
||||
"owner": "frontend-platform"
|
||||
},
|
||||
{
|
||||
"changeId": "FE-REG-STORAGE:$contract:breakingFields:contract-field-changed",
|
||||
"versionBump": "Web Storage value codec contracts start at version 1.",
|
||||
"migration": "Each existing row received an explicit codec; executable migration was never consumed and is now forbidden.",
|
||||
"compatibilityWindow": "Schema-versioned physical keys and the envelope shape remain unchanged.",
|
||||
"rollback": "Remove valueCodec enforcement and restore the prior metadata declaration.",
|
||||
"owner": "frontend-platform"
|
||||
},
|
||||
{
|
||||
"changeId": "FE-REG-STORAGE:$contract:fieldTypes:contract-field-changed",
|
||||
"versionBump": "Web Storage value codec contracts start at version 1.",
|
||||
"migration": "The dead function migration union was narrowed to the only implemented discard policy.",
|
||||
"compatibilityWindow": "All installed definitions already used discard before this contract change.",
|
||||
"rollback": "Restore the former type metadata without rewriting persisted records.",
|
||||
"owner": "frontend-platform"
|
||||
},
|
||||
{
|
||||
"changeId": "FE-REG-STORAGE:$contract:requiredFields:contract-field-changed",
|
||||
"versionBump": "Web Storage value codec contracts start at version 1.",
|
||||
"migration": "All installed storage rows now declare their closed value codec.",
|
||||
"compatibilityWindow": "Existing valid envelopes continue to decode; invalid values fail closed.",
|
||||
"rollback": "Remove the required codec field and runtime codec dispatch together.",
|
||||
"owner": "frontend-platform"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"registries": [
|
||||
{
|
||||
"registryId": "FE-REG-ROUTE",
|
||||
"path": "src/features/installed-feature-contracts.js",
|
||||
"path": "src/features/installed-feature-contracts.ts",
|
||||
"exportName": "ROUTE_REGISTRY",
|
||||
"owner": "feature-frontend-routing-release-recovery-runtime",
|
||||
"keyField": "routeId",
|
||||
@@ -92,7 +92,7 @@
|
||||
},
|
||||
{
|
||||
"registryId": "FE-REG-ROUTE-RUNTIME",
|
||||
"path": "src/features/installed-feature-contracts.js",
|
||||
"path": "src/features/installed-feature-contracts.ts",
|
||||
"exportName": "ROUTE_RUNTIME_CONTRACT",
|
||||
"owner": "feature-frontend-routing-release-recovery-runtime",
|
||||
"keyField": "routeId",
|
||||
@@ -141,7 +141,7 @@
|
||||
},
|
||||
{
|
||||
"registryId": "FE-REG-API",
|
||||
"path": "src/features/installed-feature-contracts.js",
|
||||
"path": "src/features/installed-feature-contracts.ts",
|
||||
"exportName": "API_OPERATIONS",
|
||||
"owner": "feature-frontend-api-client-response-envelope-contract",
|
||||
"keyField": "operationId",
|
||||
@@ -209,7 +209,7 @@
|
||||
},
|
||||
{
|
||||
"registryId": "FE-REG-SCHEMA",
|
||||
"path": "src/features/installed-feature-contracts.js",
|
||||
"path": "src/features/installed-feature-contracts.ts",
|
||||
"exportName": "SCHEMA_REGISTRY",
|
||||
"owner": "feature-frontend-contract-schema-registry",
|
||||
"keyField": "schemaId",
|
||||
@@ -241,7 +241,7 @@
|
||||
},
|
||||
{
|
||||
"registryId": "FE-REG-ENV",
|
||||
"path": "src/contracts/env.js",
|
||||
"path": "src/contracts/env.ts",
|
||||
"exportName": "ENV_REGISTRY",
|
||||
"owner": "feature-frontend-env-runtime-config-contract",
|
||||
"requiredFields": ["phase", "classification", "required", "defaultValue"],
|
||||
@@ -262,11 +262,11 @@
|
||||
},
|
||||
"consumers": [
|
||||
{
|
||||
"path": "src/bootstrap/runtime-config-schema.js",
|
||||
"path": "src/bootstrap/runtime-config-schema.ts",
|
||||
"token": "APP_ENV"
|
||||
},
|
||||
{
|
||||
"path": "src/contracts/env.js",
|
||||
"path": "src/contracts/env.ts",
|
||||
"token": "getBuildConfig"
|
||||
}
|
||||
],
|
||||
@@ -274,7 +274,7 @@
|
||||
},
|
||||
{
|
||||
"registryId": "FE-REG-STORAGE",
|
||||
"path": "src/contracts/storage-keys.js",
|
||||
"path": "src/contracts/storage-keys.ts",
|
||||
"exportName": "STORAGE_REGISTRY",
|
||||
"owner": "feature-frontend-storage-registry-contract",
|
||||
"keyField": "logicalName",
|
||||
@@ -284,6 +284,7 @@
|
||||
"backend",
|
||||
"classification",
|
||||
"schemaVersion",
|
||||
"valueCodec",
|
||||
"ttl",
|
||||
"migration",
|
||||
"quotaFallback"
|
||||
@@ -294,8 +295,9 @@
|
||||
"backend": "string",
|
||||
"classification": "string",
|
||||
"schemaVersion": "integer",
|
||||
"valueCodec": "string",
|
||||
"ttl": "integer|string|null",
|
||||
"migration": "string|function",
|
||||
"migration": "string",
|
||||
"quotaFallback": "string"
|
||||
},
|
||||
"uniqueFields": ["logicalName", "physicalKey"],
|
||||
@@ -304,7 +306,6 @@
|
||||
"memory",
|
||||
"sessionStorage",
|
||||
"localStorage",
|
||||
"indexedDB",
|
||||
"disabled",
|
||||
"forbidden"
|
||||
],
|
||||
@@ -313,6 +314,12 @@
|
||||
"opaque-cache",
|
||||
"sensitive-forbidden"
|
||||
],
|
||||
"valueCodec": [
|
||||
"color-scheme-v1",
|
||||
"opaque-string-v1",
|
||||
"none"
|
||||
],
|
||||
"migration": ["discard"],
|
||||
"quotaFallback": ["memory", "no-persist", "feature-disable"]
|
||||
},
|
||||
"consumerIdentityField": "logicalName",
|
||||
@@ -324,12 +331,13 @@
|
||||
"backend",
|
||||
"classification",
|
||||
"schemaVersion",
|
||||
"valueCodec",
|
||||
"migration"
|
||||
]
|
||||
},
|
||||
{
|
||||
"registryId": "FE-REG-ERROR",
|
||||
"path": "src/contracts/errors.js",
|
||||
"path": "src/contracts/errors.ts",
|
||||
"exportName": "ERROR_REGISTRY",
|
||||
"owner": "feature-frontend-error-classification-boundary-contract",
|
||||
"keyField": "kind",
|
||||
@@ -365,7 +373,7 @@
|
||||
},
|
||||
"consumers": [
|
||||
{
|
||||
"path": "src/adapters/http/client.js",
|
||||
"path": "src/adapters/http/client.ts",
|
||||
"token": "failure("
|
||||
}
|
||||
],
|
||||
@@ -373,7 +381,7 @@
|
||||
},
|
||||
{
|
||||
"registryId": "FE-REG-QUERY",
|
||||
"path": "src/features/installed-feature-contracts.js",
|
||||
"path": "src/features/installed-feature-contracts.ts",
|
||||
"exportName": "QUERY_REGISTRY",
|
||||
"owner": "feature-frontend-server-state-caching-contract",
|
||||
"requiredFields": [
|
||||
@@ -381,6 +389,8 @@
|
||||
"serialization",
|
||||
"identity",
|
||||
"invalidation",
|
||||
"invalidationTopic",
|
||||
"crossContext",
|
||||
"version",
|
||||
"persistence"
|
||||
],
|
||||
@@ -389,16 +399,19 @@
|
||||
"serialization": "string",
|
||||
"identity": "string",
|
||||
"invalidation": "string",
|
||||
"invalidationTopic": "string",
|
||||
"crossContext": "string",
|
||||
"version": "integer",
|
||||
"persistence": "string"
|
||||
},
|
||||
"uniqueFields": ["namespace"],
|
||||
"uniqueFields": ["namespace", "invalidationTopic"],
|
||||
"allowedValues": {
|
||||
"crossContext": ["invalidate-only"],
|
||||
"persistence": ["disabled"]
|
||||
},
|
||||
"consumers": [
|
||||
{
|
||||
"path": "src/features/reference-feature/contracts/reference-feature-contract.js",
|
||||
"path": "src/features/reference-feature/contracts/reference-feature-contract.ts",
|
||||
"token": "referenceQueryKeys"
|
||||
}
|
||||
],
|
||||
@@ -406,13 +419,15 @@
|
||||
"namespace",
|
||||
"serialization",
|
||||
"identity",
|
||||
"invalidationTopic",
|
||||
"crossContext",
|
||||
"version",
|
||||
"persistence"
|
||||
]
|
||||
},
|
||||
{
|
||||
"registryId": "FE-REG-TELEMETRY",
|
||||
"path": "src/contracts/telemetry.js",
|
||||
"path": "src/contracts/telemetry.ts",
|
||||
"exportName": "TELEMETRY_REGISTRY",
|
||||
"owner": "feature-frontend-diagnostics-telemetry-runtime",
|
||||
"keyField": "eventName",
|
||||
@@ -440,7 +455,7 @@
|
||||
},
|
||||
"consumers": [
|
||||
{
|
||||
"path": "scripts/check-diagnostics.mjs",
|
||||
"path": "scripts/check-diagnostics.ts",
|
||||
"token": "TELEMETRY_REGISTRY"
|
||||
}
|
||||
],
|
||||
@@ -453,7 +468,7 @@
|
||||
},
|
||||
{
|
||||
"registryId": "FE-REG-RELEASE",
|
||||
"path": "src/contracts/release-tokens.js",
|
||||
"path": "src/contracts/release-tokens.ts",
|
||||
"exportName": "RELEASE_TOKEN_REGISTRY",
|
||||
"owner": "feature-frontend-release-cache-rollback-contract",
|
||||
"keyField": "token",
|
||||
@@ -466,7 +481,7 @@
|
||||
"uniqueFields": ["token"],
|
||||
"consumers": [
|
||||
{
|
||||
"path": "src/bootstrap/load-release-manifest.js",
|
||||
"path": "src/bootstrap/load-release-manifest.ts",
|
||||
"token": "assetManifestHash"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -28,69 +28,176 @@
|
||||
{
|
||||
"id": "realtime",
|
||||
"status": "RECIPE_AVAILABLE",
|
||||
"referenceRuntime": {
|
||||
"status": "AVAILABLE_NOT_COMPOSED",
|
||||
"coveredCapabilities": [
|
||||
"transport-independent event authority and recovery",
|
||||
"bounded reconnect ownership",
|
||||
"fetch-stream SSE",
|
||||
"bounded polling",
|
||||
"single-writer live and polling handoff",
|
||||
"WebSocket closed protocol",
|
||||
"Web Push window and Service Worker control"
|
||||
],
|
||||
"sourceRoots": [
|
||||
"src/application/ports/realtime",
|
||||
"src/application/ports/out/web-push-control.ts",
|
||||
"src/application/policies/bounded-polling.ts",
|
||||
"src/contracts/realtime-events.ts",
|
||||
"src/contracts/realtime-streams.ts",
|
||||
"src/contracts/web-push.ts",
|
||||
"src/adapters/realtime",
|
||||
"src/adapters/web-push"
|
||||
],
|
||||
"conformanceScripts": [
|
||||
"test:unit",
|
||||
"check:realtime-boundaries",
|
||||
"check:realtime-boundaries:fixture",
|
||||
"check:optional-recipes",
|
||||
"test:realtime-removal"
|
||||
],
|
||||
"productionComposition": false
|
||||
},
|
||||
"trigger": "The backend exposes ordered push events with a documented resume and authorization protocol.",
|
||||
"forbiddenWhen": ["Polling satisfies the measured freshness requirement.", "Event ordering and reconnect ownership are undefined."],
|
||||
"boundary": "outbound connection plus inbound validated event adapter",
|
||||
"port": "RealtimePort",
|
||||
"fake": "FakeRealtimeAdapter",
|
||||
"failureKinds": ["disconnect", "duplicate", "out-of-order", "auth-expiry"],
|
||||
"lifecycleMethods": ["unsubscribe"],
|
||||
"boundary": "transport-independent event authority plus separately owned SSE, WebSocket, bounded polling and Web Push adapters",
|
||||
"port": "RealtimeEventAuthority / WebPushControlPort / transport-specific connection and polling factories",
|
||||
"fake": "Deterministic event authority, transport facade, clock, repository and Service Worker test doubles",
|
||||
"failureKinds": ["abort", "disconnect-or-timeout", "protocol-or-mapping-mismatch", "duplicate-or-stale", "sequence-gap-or-cursor-expiry", "queue-overflow", "scope-fenced", "poll-budget-exhausted", "push-permission-or-subscription-failure"],
|
||||
"lifecycleMethods": ["close-or-dispose", "unsubscribe", "cancel-via-AbortSignal", "bounded-poll-lease", "revoke-push-association"],
|
||||
"owner": "project-owner-required",
|
||||
"securityPrivacy": ["Validate every event envelope.", "Never place credentials in URLs or telemetry.", "Refresh authorization through the session boundary."],
|
||||
"bundleBudgetGzipBytes": 12000,
|
||||
"securityPrivacy": ["Validate every event envelope and closed transport frame before application effects.", "Bind stream state to the current opaque scope generation and advance checkpoints only after committed effects or authoritative recovery.", "Use fixed same-origin endpoints and an exact WebSocket subprotocol; never place credentials, cursors, subscription material or scope bindings in URLs or telemetry.", "Treat Web Push as a notification hint, fence registration and revocation with one durable compare-and-swap control record, and allow only registry-owned notification and route intents.", "Keep every queue, parser, reconnect, poll, notification and storage operation bounded and abortable."],
|
||||
"bundleBudgetGzipBytes": 40000,
|
||||
"fallback": "Bounded polling or explicitly stale UI.",
|
||||
"removal": ["Remove composition registration.", "Remove adapter and vendor dependency.", "Run recipe-removal and production-bundle gates."],
|
||||
"removal": ["Disable admission and close active readers, sockets, poll leases and worker handlers.", "Revoke and purge only the owned Web Push association and notification state.", "Remove composition, registries, adapters and any selected vendor dependency.", "Run realtime boundary, runtime-removal and production-bundle gates."],
|
||||
"serverStatePolicy": "query-cache-owned"
|
||||
},
|
||||
{
|
||||
"id": "offline-indexeddb",
|
||||
"status": "RECIPE_AVAILABLE",
|
||||
"trigger": "A product requirement needs durable offline data or a durable command queue beyond small public preferences.",
|
||||
"forbiddenWhen": ["The data contains credentials.", "The browser would connect directly to a database or object store.", "A normal HTTP cache is sufficient."],
|
||||
"boundary": "application-owned versioned repository output port",
|
||||
"port": "VersionedOfflineRepository",
|
||||
"fake": "MemoryOfflineRepository",
|
||||
"failureKinds": ["quota", "corruption", "migration-rollback"],
|
||||
"lifecycleMethods": ["close"],
|
||||
"referenceRuntime": {
|
||||
"status": "AVAILABLE_NOT_COMPOSED",
|
||||
"coveredCapabilities": [
|
||||
"IndexedDB",
|
||||
"OPFS",
|
||||
"StorageManager estimate/persistence"
|
||||
],
|
||||
"sourceRoots": [
|
||||
"src/application/ports/browser-file-storage/indexeddb-port.ts",
|
||||
"src/application/ports/browser-file-storage/opfs-ports.ts",
|
||||
"src/application/ports/browser-file-storage/storage-durability-port.ts",
|
||||
"src/adapters/browser-file-storage",
|
||||
"src/adapters/storage/indexeddb",
|
||||
"src/adapters/storage/opfs"
|
||||
],
|
||||
"conformanceScripts": [
|
||||
"test:unit",
|
||||
"test:browser-capabilities",
|
||||
"verify:browser-capability-evidence",
|
||||
"check:browser-file-storage-boundaries",
|
||||
"check:optional-recipes",
|
||||
"test:browser-file-storage-removal"
|
||||
],
|
||||
"productionComposition": false
|
||||
},
|
||||
"trigger": "A product requirement needs indexed offline records, an unsynced command queue, or a large local binary sidecar beyond small public preferences.",
|
||||
"forbiddenWhen": ["The data contains credentials.", "The browser would connect directly to a server database or object store.", "A normal HTTP cache is sufficient.", "Partition, retention, quota and recovery ownership are undefined."],
|
||||
"boundary": "feature-specific async repository with registry-issued opaque dataset scope and immutable full-policy binding, plus an OPFS large-object sidecar whose logical commit authority and bidirectional scope binding are owned by an IndexedDB journal",
|
||||
"port": "IndexedDbRepositoryPort / IndexedDbMaintenancePort / DurableObjectStorePort / DurableObjectMaintenancePort / StorageDurabilityPort",
|
||||
"fake": "MemoryStructuredOfflineStore / MemoryDurableObjectStore / MemoryStorageDurabilityAdapter",
|
||||
"failureKinds": ["open-blocked", "versionchange", "quota", "corruption", "migration-rollback", "revision-conflict", "storage-eviction", "partial-object-write", "dataset-binding-mismatch", "dataset-budget-exceeded", "lifecycle-authorization-denied", "expired-resource"],
|
||||
"lifecycleMethods": ["close", "cancel-via-AbortSignal", "enforce-bounded-lifecycle-batch", "prune-expired-receipts", "reconcile", "enforcePolicies-with-composition-authority"],
|
||||
"owner": "project-owner-required",
|
||||
"securityPrivacy": ["Classify persisted fields.", "Encrypting in the same client is not a credential protection boundary.", "Version and test every migration."],
|
||||
"bundleBudgetGzipBytes": 8000,
|
||||
"fallback": "Online-only query path with an explicit offline state.",
|
||||
"removal": ["Stop writes.", "Migrate or purge owned stores.", "Remove repository composition and dependency."],
|
||||
"securityPrivacy": ["Classify every persisted field and binary namespace.", "Encrypting in the same client is not a credential protection boundary.", "Keep database schema and record codec versions separate.", "Derive the physical IndexedDB name only from registry-issued authority, namespace and partition tokens; readable namespace, business and account IDs are forbidden.", "Persist and revalidate an immutable scope plus full BrowserStoragePolicy binding during upgrade, post-open and maintenance; missing or mismatched existing bindings fail closed.", "Use the actual IndexedDB wire split: StoredRecord contains only key, codecVersion, revision and payload; writtenAtEpochMs, synchronization, measuredBytes and eligibleAtEpochMs belong to the retention sidecar, while idempotency receipts and governance binding/budget use separate stores.", "Include every store registered in lifecycleMetadataStores in bounded full-partition purge while retaining immutable governance identity.", "Measure conservative logical bytes through the codec and atomically enforce dataset usedBytes plus receiptCount with record, lifecycle and migration writes.", "Enforce TTL before sweep visibility, delete UNTIL_SYNCED only after explicit confirmation, and require a composition-authorized short-lived proof for every deleting IndexedDB lifecycle batch.", "Bound idempotency receipt retention to 31 days and configured count to the implementation ceiling of 1000000; bound migration to old-writer-drained batches no larger than 500 rows or 30000ms.", "Bind OPFS readable and physical scopes in both directions and use only /ca-frontend-opfs-v1/authorities/<authorityToken>/<namespaceToken>/<partitionToken>/ for physical dataset layout.", "For OPFS LOGOUT, UNTIL_SYNCED and ACCOUNT_DELETION maintenance, composition must provide both requestMaintenanceAuthority and consumeMaintenanceAuthority; issue a fresh proof bound to the exact frozen reason, scope and policy for at most five minutes, then atomically consume it to reject replay.", "Never expose an OPFS authority proof through the application request, persistence, diagnostics or telemetry.", "Never place user file names or identifiers in OPFS paths or diagnostics."],
|
||||
"bundleBudgetGzipBytes": 36000,
|
||||
"fallback": "Read-only or online-only query path; OPFS may degrade to a size-capped IndexedDB Blob only when the product policy approves it.",
|
||||
"removal": ["Stop writes and background migration.", "Reconcile or export unsynced data, then purge only governance-bound owned partitions and OPFS namespaces through authorized bounded lifecycle operations.", "Close all database, channel, worker and file handles.", "Remove repository composition and dependency."],
|
||||
"serverStatePolicy": "reference-or-command-only"
|
||||
},
|
||||
{
|
||||
"id": "service-worker-pwa",
|
||||
"status": "RECIPE_AVAILABLE",
|
||||
"trigger": "Installability or a measured offline-shell requirement is approved with cache ownership.",
|
||||
"forbiddenWhen": ["Hosting cache and worker cache ownership conflict.", "Update and rollback UX is undefined."],
|
||||
"boundary": "bootstrap update controller and cache policy adapter",
|
||||
"port": "ServiceWorkerUpdatePort",
|
||||
"fake": "FakeServiceWorkerUpdateAdapter",
|
||||
"failureKinds": ["stale-worker", "update-loop", "offline-fallback"],
|
||||
"lifecycleMethods": ["unregister", "rollback"],
|
||||
"referenceRuntime": {
|
||||
"status": "AVAILABLE_NOT_COMPOSED",
|
||||
"coveredCapabilities": [
|
||||
"Cache Storage public-response administration"
|
||||
],
|
||||
"sourceRoots": [
|
||||
"src/application/ports/browser-file-storage/cache-storage-ports.ts",
|
||||
"src/adapters/browser-file-storage",
|
||||
"src/adapters/cache-storage"
|
||||
],
|
||||
"conformanceScripts": [
|
||||
"test:unit",
|
||||
"test:browser-capabilities",
|
||||
"verify:browser-capability-evidence",
|
||||
"check:browser-file-storage-boundaries",
|
||||
"check:optional-recipes",
|
||||
"test:browser-file-storage-removal"
|
||||
],
|
||||
"productionComposition": false
|
||||
},
|
||||
"trigger": "Installability, a measured offline-shell requirement, or an explicitly owned public HTTP representation cache is approved.",
|
||||
"forbiddenWhen": ["Hosting cache and worker cache ownership conflict.", "Update and rollback UX is undefined.", "Authenticated, private, opaque or personal responses would be cached.", "Cache freshness, byte and entry limits are undefined."],
|
||||
"boundary": "bootstrap update controller plus platform-local public Request/Response cache administration",
|
||||
"port": "ServiceWorkerUpdatePort / PublicResponseCacheAdmin recipe / PublicResponseCachePort / PublicResponseCacheAdminPort reference runtime",
|
||||
"fake": "FakeServiceWorkerUpdateAdapter / MemoryPublicResponseCache",
|
||||
"failureKinds": ["stale-worker", "update-loop", "offline-fallback", "incomplete-candidate", "integrity-mismatch", "cache-policy-rejection", "quota"],
|
||||
"lifecycleMethods": ["unregister", "rollback", "delete-owned-caches"],
|
||||
"owner": "project-owner-required",
|
||||
"securityPrivacy": ["Never cache authenticated API responses by default.", "Bind cache names to release identity.", "Fail closed on malformed update metadata."],
|
||||
"securityPrivacy": ["Cache only explicit same-origin public GET representations.", "Never cache authenticated, cookie-dependent, private, no-store, opaque or personal responses.", "Bind candidate cache names to release identity and a canonical manifest digest that includes normalized expectedContentType, exact request identity, expected byte length and integrity digest.", "Reject a response whose normalized Content-Type differs from manifest expectedContentType even when body integrity matches.", "Derive cleanup retention only from the verified active pointer and composition retainedPreviousReleaseCount; cleanup callers cannot submit cache names, release registry IDs or any retain set.", "Read active-pointer and release-marker control JSON through a strict UTF-8 stream capped at exactly 2 MiB (2097152 bytes), cancel on overflow and fail closed before parsing oversized metadata.", "Keep exact query and Vary semantics; ignoreSearch and ignoreVary are forbidden.", "Fail closed on malformed update metadata or integrity mismatch."],
|
||||
"bundleBudgetGzipBytes": 10000,
|
||||
"fallback": "Normal network application with hosting cache headers.",
|
||||
"removal": ["Deploy an unregister migration.", "Delete owned caches.", "Remove worker registration and manifest."],
|
||||
"removal": ["Deploy an unregister migration.", "Delete only parsed, owned cache namespaces after old controlled clients drain.", "Remove worker registration, cache metadata and manifest."],
|
||||
"serverStatePolicy": "network-cache-policy-only"
|
||||
},
|
||||
{
|
||||
"id": "file-transfer",
|
||||
"status": "RECIPE_AVAILABLE",
|
||||
"trigger": "The product accepts or delivers files with progress and cancellation requirements.",
|
||||
"forbiddenWhen": ["Allowed size and MIME policy is missing.", "Long-lived credentials would be embedded in URLs."],
|
||||
"boundary": "application file transfer output port behind an authorized backend protocol",
|
||||
"port": "FileTransferPort",
|
||||
"fake": "FakeFileTransferAdapter",
|
||||
"failureKinds": ["size-rejection", "type-rejection", "abort", "expired-url"],
|
||||
"lifecycleMethods": ["cancel-via-AbortSignal"],
|
||||
"referenceRuntime": {
|
||||
"status": "AVAILABLE_NOT_COMPOSED",
|
||||
"coveredCapabilities": [
|
||||
"File",
|
||||
"Blob",
|
||||
"native file input",
|
||||
"system file picker",
|
||||
"object URL preview",
|
||||
"download delivery",
|
||||
"presigned URL capability",
|
||||
"bounded streaming download",
|
||||
"multipart/resumable upload",
|
||||
"durable non-secret upload checkpoint",
|
||||
"Image CDN responsive delivery"
|
||||
],
|
||||
"sourceRoots": [
|
||||
"src/application/ports/browser-file-storage/file.ts",
|
||||
"src/application/ports/browser-transfer",
|
||||
"src/adapters/browser-file-storage",
|
||||
"src/adapters/browser-files",
|
||||
"src/adapters/browser-transfer"
|
||||
],
|
||||
"conformanceScripts": [
|
||||
"test:unit",
|
||||
"test:browser-capabilities",
|
||||
"verify:browser-capability-evidence",
|
||||
"check:browser-file-storage-boundaries",
|
||||
"check:optional-recipes",
|
||||
"test:browser-file-storage-removal"
|
||||
],
|
||||
"productionComposition": false
|
||||
},
|
||||
"trigger": "The product selects, inspects, previews, uploads, downloads or delivers image renditions with bounded memory, resumability, cancellation, expiry and integrity requirements.",
|
||||
"forbiddenWhen": ["Allowed count, byte, extension, MIME and content-signature policy is missing.", "The BFF does not own authorization, short-lived capability issuance, upload session reconciliation, quarantine and orphan cleanup.", "Long-lived credentials, presigned URLs or signed headers would enter persistence, application state or telemetry.", "Native File, Blob, object URL or file-system handles would cross into domain state or persistence.", "Large downloads would be returned as one in-memory byte array or Blob.", "Image callers could submit arbitrary CDN source URLs or transform parameters."],
|
||||
"boundary": "BFF-owned transfer control plane plus adapter-owned browser/object-storage data plane; presentation receives opaque file/image references, registered policies and bounded result streams only",
|
||||
"port": "FilePickerPort / FileContentPort / TransientPreviewPort / DownloadDeliveryPort / PresignedDownloadSourcePort / PresignedUploadPartPort / ResumableUploadPort / ImageCdnPresentationPort",
|
||||
"fake": "Memory file/preview/download adapters plus injected deterministic capability, upload-control-plane, part-executor and image-verifier test doubles",
|
||||
"failureKinds": ["dismissed", "permission-denied", "count-or-size-rejection", "type-or-signature-rejection", "file-changed", "abort", "integrity-failure", "partial-save", "expired-or-revoked-capability", "part-or-session-conflict", "checkpoint-conflict", "quarantined", "image-policy-rejection"],
|
||||
"lifecycleMethods": ["release-file-ref", "release-or-dispose-preview-leases", "cancel-via-AbortSignal", "reconcile-or-explicitly-abort-upload", "close-checkpoint-store", "dispose-capability-and-image-runtime"],
|
||||
"owner": "project-owner-required",
|
||||
"securityPrivacy": ["Treat MIME as untrusted metadata.", "Use short-lived opaque resource identifiers.", "Redact file names when classified as personal data."],
|
||||
"bundleBudgetGzipBytes": 6000,
|
||||
"fallback": "Standard request with bounded size and no background continuation.",
|
||||
"removal": ["Cancel active transfers.", "Remove route actions and composition.", "Remove transfer dependency."],
|
||||
"securityPrivacy": ["Treat file name, extension, MIME and lastModified as untrusted metadata.", "Resolve only exact composition-issued file and image policy object identities; callers cannot raise byte, candidate, pixel, quality, format, lifetime or origin ceilings.", "Use opaque file references and verification receipts bound to an inspected immutable file snapshot and the exact registered profile; reject replay through another profile even when an inspection rule ID matches.", "Treat presigned URLs as bearer capabilities; bind exact method, resource or upload part, offset, length, media type, checksum, origin, path, query, headers and expiry in an in-memory identity vault.", "Use credentials omit, redirect error, no-referrer and no-store for direct data-plane fetch; never persist or observe URL, query, signed header, capability, file name or raw backend message, and never emit digest, raw ETag or receipt values to diagnostics or telemetry.", "A strict account-partitioned upload checkpoint may persist only the protocol-defined SHA-256 file fingerprint, per-part checksum and bounded opaque non-authorizing part receipt token required for server reconciliation; no bearer token or raw signed capability is allowed.", "Persist only strict non-authorizing upload checkpoints and reconcile them with server-authoritative status and re-hashed local parts before completion.", "Require a synchronous server-issued browser-managed download capability whose receipt exactly equals the caller's branded capability receipt and whose resource, media type, safe extension, maximum bytes, optional digest and expiry all match before handoff.", "Expose File, OPFS, Cache and transfer byte streams only as chunk-level closed Results; stop after the first failure, cancel native readers and never throw a raw native exception across the port.", "Accept Image CDN assets only through immutable allowlisted or signature-verified descriptors and registered preset identities; reject active formats, arbitrary transforms, pixel/decode-budget overflow and unsafe cache policy.", "Upload completion remains QUARANTINED until backend scan and promotion; client capability checks are not an authorization boundary.", "Active content preview requires isolation or download-only treatment."],
|
||||
"bundleBudgetGzipBytes": 52000,
|
||||
"fallback": "Accessible native file input, same-origin authorized server upload/download and a single bounded server-selected image rendition; generated artifacts above the buffer budget move to server-side generation.",
|
||||
"removal": ["Stop new capability and upload-session issuance, then cancel active reads and transfers.", "Reconcile or explicitly abort active multipart sessions and let backend TTL cleanup remove ambiguous orphans.", "Remove non-secret checkpoints according to account and retention policy.", "Release file references, revoke preview object-URL leases and dispose file, capability and image runtimes.", "Remove transfer/image feature facades and composition, then prove browser-transfer sources are absent from the production module inventory."],
|
||||
"serverStatePolicy": "query-cache-metadata-only"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
".storybook",
|
||||
"package.json",
|
||||
"pnpm-lock.yaml",
|
||||
"vite.config.js",
|
||||
"vitest.config.js",
|
||||
"playwright.config.js"
|
||||
"vite.config.ts",
|
||||
"vitest.config.ts",
|
||||
"playwright.config.ts"
|
||||
],
|
||||
"generatedRoots": ["dist", "artifacts/release"],
|
||||
"excludedPaths": [
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
},
|
||||
"criticalModules": [
|
||||
{
|
||||
"path": "src/adapters/http/retry-policy.js",
|
||||
"path": "src/adapters/http/retry-policy.ts",
|
||||
"minimum": {
|
||||
"lines": 80,
|
||||
"statements": 78,
|
||||
@@ -17,7 +17,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "src/adapters/storage/browser-storage-adapter.js",
|
||||
"path": "src/adapters/storage/browser-storage-adapter.ts",
|
||||
"minimum": {
|
||||
"lines": 60,
|
||||
"statements": 60,
|
||||
@@ -26,7 +26,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "src/adapters/telemetry/best-effort-telemetry.js",
|
||||
"path": "src/adapters/telemetry/best-effort-telemetry.ts",
|
||||
"minimum": {
|
||||
"lines": 85,
|
||||
"statements": 85,
|
||||
@@ -35,7 +35,16 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "src/application/policies/compatibility.js",
|
||||
"path": "src/application/create-application.ts",
|
||||
"minimum": {
|
||||
"lines": 90,
|
||||
"statements": 90,
|
||||
"functions": 80,
|
||||
"branches": 68
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "src/application/policies/compatibility.ts",
|
||||
"minimum": {
|
||||
"lines": 95,
|
||||
"statements": 95,
|
||||
@@ -44,7 +53,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "src/application/policies/performance-budgets.js",
|
||||
"path": "src/application/policies/performance-budgets.ts",
|
||||
"minimum": {
|
||||
"lines": 80,
|
||||
"statements": 80,
|
||||
@@ -53,7 +62,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "src/application/policies/promotion-readiness.js",
|
||||
"path": "src/application/policies/promotion-readiness.ts",
|
||||
"minimum": {
|
||||
"lines": 95,
|
||||
"statements": 95,
|
||||
@@ -62,7 +71,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "src/application/use-cases/decide-chunk-recovery.js",
|
||||
"path": "src/application/use-cases/decide-chunk-recovery.ts",
|
||||
"minimum": {
|
||||
"lines": 90,
|
||||
"statements": 90,
|
||||
@@ -80,7 +89,25 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "scripts/lib/registry-compatibility.mjs",
|
||||
"path": "src/features/reference-feature/adapters/reference-http-gateway.ts",
|
||||
"minimum": {
|
||||
"lines": 90,
|
||||
"statements": 90,
|
||||
"functions": 90,
|
||||
"branches": 90
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "src/presentation/adapters/query/application-query.ts",
|
||||
"minimum": {
|
||||
"lines": 90,
|
||||
"statements": 90,
|
||||
"functions": 90,
|
||||
"branches": 80
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "scripts/lib/registry-compatibility.ts",
|
||||
"minimum": {
|
||||
"lines": 80,
|
||||
"statements": 80,
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"scenarioCatalogs": [
|
||||
{
|
||||
"owner": "reference-feature",
|
||||
"path": "tests/mocks/scenarios/catalog.ts",
|
||||
"arrayExport": "HTTP_SCENARIO_IDS",
|
||||
"minimumEntries": 19
|
||||
}
|
||||
],
|
||||
"sourceContracts": [
|
||||
{
|
||||
"owner": "reference-feature",
|
||||
"path": "tests/mocks/handlers/reference-resources.ts",
|
||||
"requiredTokens": [
|
||||
"assertOperationScenario",
|
||||
"../scenarios/catalog.ts"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user