@tokenoftrust/storefront-runner 2.0.17 → 2.0.19

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.
Files changed (98) hide show
  1. package/apps/storefront/env.d.ts +21 -0
  2. package/apps/storefront/migrations-apps/0012_test_destinations.sql +29 -0
  3. package/apps/storefront/src/components/blog/ReactionBar.astro +1 -1
  4. package/apps/storefront/src/components/islands/CheckoutComplianceGate.tsx +365 -49
  5. package/apps/storefront/src/components/islands/checkoutVerificationFlow.ts +251 -0
  6. package/apps/storefront/src/config/compliance/rulesets.ts +18 -7
  7. package/apps/storefront/src/config/devTenantSeed.ts +24 -1
  8. package/apps/storefront/src/config/evidenceTenantRoster.ts +25 -0
  9. package/apps/storefront/src/config/publicationSpaceConfig.ts +25 -0
  10. package/apps/storefront/src/config/resolver.ts +5 -0
  11. package/apps/storefront/src/config/tenantAnalyticsFiles.ts +43 -0
  12. package/apps/storefront/src/config/tenants.ts +11 -0
  13. package/apps/storefront/src/layouts/Layout.astro +5 -1
  14. package/apps/storefront/src/lib/activity/killSwitch.ts +1 -1
  15. package/apps/storefront/src/lib/admin/consentSettingsClient.ts +113 -0
  16. package/apps/storefront/src/lib/apps/consentConfigRead.ts +24 -0
  17. package/apps/storefront/src/lib/apps/gtmMigrationDraft.ts +103 -0
  18. package/apps/storefront/src/lib/auth/brokerAssertion.ts +18 -0
  19. package/apps/storefront/src/lib/auth/identityToken.ts +11 -1
  20. package/apps/storefront/src/lib/auth/internalContentAuthority.ts +153 -0
  21. package/apps/storefront/src/lib/auth/loginGate.ts +25 -0
  22. package/apps/storefront/src/lib/auth/session.ts +3 -0
  23. package/apps/storefront/src/lib/checkoutCommerce.ts +1 -1
  24. package/apps/storefront/src/lib/compliance/enforcement.ts +25 -3
  25. package/apps/storefront/src/lib/d1/schema-apps.ts +44 -0
  26. package/apps/storefront/src/lib/edgeCache.ts +17 -1
  27. package/apps/storefront/src/lib/env.ts +13 -111
  28. package/apps/storefront/src/lib/integration/tenantAnalyticsDeclarations.ts +198 -0
  29. package/apps/storefront/src/lib/monitoring/manifest.ts +1 -1
  30. package/apps/storefront/src/lib/publication/contentProvider.ts +159 -0
  31. package/apps/storefront/src/lib/publication/runtimeSource.ts +97 -0
  32. package/apps/storefront/src/lib/rawMarketingHtml.ts +9 -1
  33. package/apps/storefront/src/lib/runtimeEnv.ts +124 -0
  34. package/apps/storefront/src/lib/verification/totVerificationClient.ts +485 -0
  35. package/apps/storefront/src/middleware/candidatePin.ts +35 -0
  36. package/apps/storefront/src/middleware/controlPlane.ts +291 -0
  37. package/apps/storefront/src/middleware/index.ts +200 -793
  38. package/apps/storefront/src/middleware/publicRender.ts +43 -0
  39. package/apps/storefront/src/middleware/renderChain.ts +730 -0
  40. package/apps/storefront/src/middleware/routeBranch.ts +192 -0
  41. package/apps/storefront/src/middleware/staticBundle.ts +109 -0
  42. package/apps/storefront/src/pages/[...slug].astro +1 -0
  43. package/apps/storefront/src/pages/api/auth/magic-exchange.ts +1 -0
  44. package/apps/storefront/src/pages/api/auth/step-up-verify.ts +1 -0
  45. package/apps/storefront/src/pages/api/auth/verify.ts +1 -0
  46. package/apps/storefront/src/pages/api/compliance/preflight.ts +179 -2
  47. package/apps/storefront/src/pages/index.astro +1 -0
  48. package/apps/storefront/vitest.config.ts +5 -0
  49. package/package.json +1 -1
  50. package/packages/public-runtime/package.json +1 -0
  51. package/packages/public-runtime/schemas/managed-analytics/v1/deliver-test-event-request.schema.json +122 -0
  52. package/packages/public-runtime/schemas/managed-analytics/v1/get-test-destination-delivery-request.schema.json +79 -0
  53. package/packages/public-runtime/schemas/managed-analytics/v1/register-test-destination-request.schema.json +93 -0
  54. package/packages/public-runtime/schemas/managed-analytics/v1/test-destination-delivery.schema.json +106 -0
  55. package/packages/public-runtime/schemas/managed-analytics/v1/test-destination.schema.json +77 -0
  56. package/packages/public-runtime/schemas/publication-space/v1/manifest.schema.json +195 -0
  57. package/packages/public-runtime/schemas/publication-space/v1/normalized-mount.schema.json +80 -0
  58. package/packages/public-runtime/schemas/publication-space/v1/ref.schema.json +20 -0
  59. package/packages/public-runtime/schemas/publication-version/v1/pointer.schema.json +28 -0
  60. package/packages/public-runtime/schemas/publication-version/v1/transition-request.schema.json +44 -0
  61. package/packages/public-runtime/schemas/publication-version/v1/transition.schema.json +47 -0
  62. package/packages/public-runtime/schemas/publication-version/v1/version.schema.json +58 -0
  63. package/packages/public-runtime/src/activity/catalog.ts +1 -1
  64. package/packages/public-runtime/src/candidate-index.ts +6 -0
  65. package/packages/public-runtime/src/customization-reconcile.ts +8 -0
  66. package/packages/public-runtime/src/html-cache-policy.ts +57 -0
  67. package/packages/public-runtime/src/index.ts +9 -0
  68. package/packages/public-runtime/src/integration/consent-broker.ts +115 -0
  69. package/packages/public-runtime/src/integration/interim-bridge.ts +111 -27
  70. package/packages/public-runtime/src/integration/managed-analytics-api-v1.schemas.ts +65 -0
  71. package/packages/public-runtime/src/integration/managed-analytics-api-v1.ts +81 -0
  72. package/packages/public-runtime/src/integration/render-phases.ts +8 -3
  73. package/packages/public-runtime/src/publication-artifact.ts +220 -0
  74. package/packages/public-runtime/src/publication-reader.ts +187 -0
  75. package/packages/public-runtime/src/publication-routing.ts +246 -0
  76. package/packages/public-runtime/src/publication-space.ts +853 -0
  77. package/packages/public-runtime/src/publication-version.ts +602 -0
  78. package/packages/public-runtime/src/route-tier.ts +257 -0
  79. package/packages/public-runtime/src/static-bundle.ts +18 -5
  80. package/packages/public-runtime/src/tenant-assets.ts +85 -17
  81. package/packages/public-runtime/src/tenant.ts +70 -0
  82. package/packages/public-runtime/tests/fixtures/publication-spaces/internal.json +32 -0
  83. package/packages/public-runtime/tests/fixtures/publication-spaces/mounted-public.json +38 -0
  84. package/packages/public-runtime/tests/fixtures/publication-spaces/normalized-mounts.json +39 -0
  85. package/packages/public-runtime/tests/fixtures/publication-spaces/ref.json +5 -0
  86. package/packages/public-runtime/tests/fixtures/publication-spaces/root-public.json +31 -0
  87. package/packages/public-runtime/tests/fixtures/publication-versions/articles-v1.json +20 -0
  88. package/packages/public-runtime/tests/fixtures/publication-versions/articles-v2.json +20 -0
  89. package/packages/public-runtime/tests/fixtures/publication-versions/internal-v1.json +20 -0
  90. package/packages/public-runtime/tests/fixtures/publication-versions/live-pointer.json +11 -0
  91. package/packages/public-runtime/tests/fixtures/publication-versions/live-transition-request.json +14 -0
  92. package/packages/public-runtime/tests/fixtures/publication-versions/live-transition.json +17 -0
  93. package/packages/public-runtime/tests/fixtures/publication-versions/root-v1.json +20 -0
  94. package/packages/public-runtime/tests/fixtures/publication-versions/root-v2.json +20 -0
  95. package/scripts/dev/ai-edit.mjs +16 -3
  96. package/scripts/dev/port-check.mjs +18 -3
  97. package/scripts/dev/publish.mjs +26 -3
  98. package/scripts/tenant/validate.mjs +14 -1
@@ -0,0 +1,195 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://tokenoftrust.com/schemas/publication-space/v1/manifest.schema.json",
4
+ "title": "PublicationSpaceManifestV1",
5
+ "$comment": "This schema provides portable structural and lexical validation, including literal reserved mounts. validatePublicationSpaceManifestV1 enforces the same policy after path normalization.",
6
+ "type": "object",
7
+ "patternProperties": { "^\\$(?:schema|comment|id)$": {} },
8
+ "additionalProperties": false,
9
+ "required": [
10
+ "version",
11
+ "id",
12
+ "tenant",
13
+ "source",
14
+ "routes",
15
+ "visibility",
16
+ "authorization",
17
+ "discovery",
18
+ "assets",
19
+ "renderer"
20
+ ],
21
+ "properties": {
22
+ "version": { "const": 1 },
23
+ "id": { "$ref": "#/$defs/identifier" },
24
+ "tenant": { "$ref": "#/$defs/identifier" },
25
+ "source": {
26
+ "type": "object",
27
+ "patternProperties": { "^\\$(?:schema|comment|id)$": {} },
28
+ "additionalProperties": false,
29
+ "required": ["forge", "repo", "defaultBranch"],
30
+ "properties": {
31
+ "forge": { "enum": ["gitea", "github", "fixture"] },
32
+ "repo": {
33
+ "type": "string",
34
+ "minLength": 1,
35
+ "maxLength": 256,
36
+ "pattern": "^(?!.*\\.\\.)(?!.*//)[A-Za-z0-9](?:[A-Za-z0-9._/-]{0,254}[A-Za-z0-9])?$"
37
+ },
38
+ "defaultBranch": {
39
+ "type": "string",
40
+ "minLength": 1,
41
+ "maxLength": 256,
42
+ "pattern": "^(?![-/.])(?!HEAD$)(?!.*(?:/\\.|\\.\\.|@\\{|\\\\|\\s|~|\\^|:|\\?|\\*|\\[|//))(?!.*(?:^|/)[^/]*\\.lock(?:/|$))(?!.*[/.]$)[A-Za-z0-9._/-]+$"
43
+ }
44
+ }
45
+ },
46
+ "routes": {
47
+ "type": "object",
48
+ "patternProperties": { "^\\$(?:schema|comment|id)$": {} },
49
+ "additionalProperties": false,
50
+ "required": ["canonicalMount"],
51
+ "properties": {
52
+ "canonicalMount": { "$ref": "#/$defs/mountPath" },
53
+ "aliases": {
54
+ "type": "array",
55
+ "items": {
56
+ "oneOf": [
57
+ {
58
+ "type": "object",
59
+ "patternProperties": { "^\\$(?:schema|comment|id)$": {} },
60
+ "additionalProperties": false,
61
+ "required": ["from", "behavior"],
62
+ "properties": {
63
+ "from": { "$ref": "#/$defs/aliasPath" },
64
+ "behavior": { "const": "render" }
65
+ }
66
+ },
67
+ {
68
+ "type": "object",
69
+ "patternProperties": { "^\\$(?:schema|comment|id)$": {} },
70
+ "additionalProperties": false,
71
+ "required": ["from", "behavior", "to"],
72
+ "properties": {
73
+ "from": { "$ref": "#/$defs/aliasPath" },
74
+ "behavior": { "const": "redirect-308" },
75
+ "to": { "$ref": "#/$defs/path" }
76
+ }
77
+ }
78
+ ]
79
+ }
80
+ }
81
+ }
82
+ },
83
+ "visibility": { "enum": ["public", "internal"] },
84
+ "authorization": {
85
+ "oneOf": [
86
+ {
87
+ "type": "object",
88
+ "patternProperties": { "^\\$(?:schema|comment|id)$": {} },
89
+ "additionalProperties": false,
90
+ "required": ["policy"],
91
+ "properties": { "policy": { "const": "public" } }
92
+ },
93
+ {
94
+ "type": "object",
95
+ "patternProperties": { "^\\$(?:schema|comment|id)$": {} },
96
+ "additionalProperties": false,
97
+ "required": ["policy", "capability"],
98
+ "properties": {
99
+ "policy": { "const": "capability" },
100
+ "capability": { "const": "internal-content-reader" }
101
+ }
102
+ }
103
+ ]
104
+ },
105
+ "discovery": {
106
+ "type": "object",
107
+ "patternProperties": { "^\\$(?:schema|comment|id)$": {} },
108
+ "additionalProperties": false,
109
+ "required": ["sitemap", "feeds", "publicSearch", "llms"],
110
+ "properties": {
111
+ "sitemap": { "type": "boolean" },
112
+ "feeds": { "type": "boolean" },
113
+ "publicSearch": { "type": "boolean" },
114
+ "llms": { "type": "boolean" }
115
+ }
116
+ },
117
+ "assets": {
118
+ "type": "object",
119
+ "patternProperties": { "^\\$(?:schema|comment|id)$": {} },
120
+ "additionalProperties": false,
121
+ "required": ["namespace", "access"],
122
+ "properties": {
123
+ "namespace": { "$ref": "#/$defs/identifier" },
124
+ "access": { "enum": ["public", "authorized"] }
125
+ }
126
+ },
127
+ "renderer": {
128
+ "type": "object",
129
+ "patternProperties": { "^\\$(?:schema|comment|id)$": {} },
130
+ "additionalProperties": false,
131
+ "required": ["contractVersion", "themeContractVersion"],
132
+ "properties": {
133
+ "contractVersion": { "type": "string", "minLength": 1 },
134
+ "themeContractVersion": { "type": "string", "minLength": 1 }
135
+ }
136
+ }
137
+ },
138
+ "allOf": [
139
+ {
140
+ "if": { "type": "object", "properties": { "visibility": { "const": "public" } } },
141
+ "then": {
142
+ "type": "object",
143
+ "properties": {
144
+ "authorization": { "type": "object", "properties": { "policy": { "const": "public" } } },
145
+ "assets": { "type": "object", "properties": { "access": { "const": "public" } } }
146
+ }
147
+ }
148
+ },
149
+ {
150
+ "if": { "type": "object", "properties": { "visibility": { "const": "internal" } } },
151
+ "then": {
152
+ "type": "object",
153
+ "properties": {
154
+ "authorization": { "type": "object", "properties": { "policy": { "const": "capability" } } },
155
+ "assets": { "type": "object", "properties": { "access": { "const": "authorized" } } },
156
+ "discovery": {
157
+ "type": "object",
158
+ "properties": {
159
+ "sitemap": { "const": false },
160
+ "feeds": { "const": false },
161
+ "publicSearch": { "const": false },
162
+ "llms": { "const": false }
163
+ }
164
+ }
165
+ }
166
+ }
167
+ }
168
+ ],
169
+ "$defs": {
170
+ "identifier": {
171
+ "type": "string",
172
+ "pattern": "^[a-z0-9](?:[a-z0-9._-]{0,126}[a-z0-9])?$"
173
+ },
174
+ "path": {
175
+ "type": "string",
176
+ "not": {
177
+ "type": "string",
178
+ "pattern": "^/(?:(?:%25(?:2|%32)(?:[Ee]|%45|%65))){1,2}(?:/|$)"
179
+ },
180
+ "pattern": "^/(?!(?:(?:\\.|%2[eE])){1,2}(?:/|$))(?!.*/(?:(?:\\.|%2[eE])){1,2}(?:/|$))(?!.*%(?:2[fF]|5[cC]))(?!.*%25(?:(?:0|%30|1|%31)(?:[0-9A-Fa-f]|%3[0-9]|%4[1-6]|%6[1-6])|(?:2|%32)(?:[Ff]|%46|%66)|(?:5|%35)(?:[Cc]|%43|%63)|(?:7|%37)(?:[Ff]|%46|%66)))(?!.*\/(?:(?:%25(?:2|%32)(?:[Ee]|%45|%65))){1,2}(?:/|$))(?!.*[?#\\\\\\u0000-\\u001F\\u007F\\uD800-\\uDFFF])(?:[^%?#\\\\\\u0000-\\u001F\\u007F\\uD800-\\uDFFF]|%(?:2[0-9A-Ea-e]|[34][0-9A-Fa-f]|5[0-9A-Ba-bD-Fd-f]|6[0-9A-Fa-f]|7[0-9A-Ea-e])|%(?:[Cc][2-9A-Fa-f]|[Dd][0-9A-Fa-f])%(?:[89AaBb][0-9A-Fa-f])|%[Ee]0%(?:[AaBb][0-9A-Fa-f])%(?:[89AaBb][0-9A-Fa-f])|%[Ee][1-9A-Ca-cEFef]%(?:[89AaBb][0-9A-Fa-f])%(?:[89AaBb][0-9A-Fa-f])|%[Ee][Dd]%(?:[89][0-9A-Fa-f])%(?:[89AaBb][0-9A-Fa-f])|%[Ff]0%(?:[9AaBb][0-9A-Fa-f])%(?:[89AaBb][0-9A-Fa-f])%(?:[89AaBb][0-9A-Fa-f])|%[Ff][1-3]%(?:[89AaBb][0-9A-Fa-f])%(?:[89AaBb][0-9A-Fa-f])%(?:[89AaBb][0-9A-Fa-f])|%[Ff]4%8[0-9A-Fa-f]%(?:[89AaBb][0-9A-Fa-f])%(?:[89AaBb][0-9A-Fa-f]))*$"
181
+ },
182
+ "mountPath": {
183
+ "allOf": [
184
+ { "$ref": "#/$defs/path" },
185
+ { "type": "string", "pattern": "^/(?!(?:\\.well-known|__evidence|__preview|_astro|_style-guide|admin|api|apps|assets|auth|brand|capabilities|cockpit|collections|dashboard|dev|favicon\\.svg|health|js|llms\\.txt|platform|preview|products|robots\\.txt|saved|search|shared|sitemap\\.xml|style-guide|tenants)(?:/|$))" }
186
+ ]
187
+ },
188
+ "aliasPath": {
189
+ "allOf": [
190
+ { "$ref": "#/$defs/mountPath" },
191
+ { "type": "string", "pattern": "^/.+" }
192
+ ]
193
+ }
194
+ }
195
+ }
@@ -0,0 +1,80 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://tokenoftrust.com/schemas/publication-space/v1/normalized-mount.schema.json",
4
+ "title": "NormalizedPublicationMountEntryV1",
5
+ "$comment": "This schema provides portable structural and lexical validation. Cross-property equality/inequality and Unicode NFC are enforced by validateNormalizedPublicationMountEntryV1 because JSON Schema 2020-12 cannot compare property values or normalize Unicode.",
6
+ "type": "object",
7
+ "patternProperties": { "^\\$(?:schema|comment|id)$": {} },
8
+ "additionalProperties": false,
9
+ "required": ["version", "tenant", "spaceId", "kind", "mount", "canonicalMount", "behavior"],
10
+ "properties": {
11
+ "version": { "const": 1 },
12
+ "tenant": { "$ref": "#/$defs/identifier" },
13
+ "spaceId": { "$ref": "#/$defs/identifier" },
14
+ "kind": { "enum": ["canonical", "alias"] },
15
+ "mount": { "$ref": "#/$defs/mountPath" },
16
+ "canonicalMount": { "$ref": "#/$defs/mountPath" },
17
+ "behavior": { "enum": ["render", "redirect-308"] },
18
+ "redirectTo": { "$ref": "#/$defs/normalizedPath" }
19
+ },
20
+ "allOf": [
21
+ {
22
+ "if": { "type": "object", "properties": { "kind": { "const": "canonical" } } },
23
+ "then": {
24
+ "type": "object",
25
+ "properties": { "behavior": { "const": "render" } },
26
+ "not": {
27
+ "type": "object",
28
+ "properties": { "redirectTo": {} },
29
+ "required": ["redirectTo"]
30
+ }
31
+ }
32
+ },
33
+ {
34
+ "if": { "type": "object", "properties": { "kind": { "const": "alias" } } },
35
+ "then": { "type": "object", "properties": { "mount": { "$ref": "#/$defs/aliasPath" } } }
36
+ },
37
+ {
38
+ "if": { "type": "object", "properties": { "behavior": { "const": "render" } } },
39
+ "then": {
40
+ "type": "object",
41
+ "not": {
42
+ "type": "object",
43
+ "properties": { "redirectTo": {} },
44
+ "required": ["redirectTo"]
45
+ }
46
+ }
47
+ },
48
+ {
49
+ "if": { "type": "object", "properties": { "behavior": { "const": "redirect-308" } } },
50
+ "then": {
51
+ "type": "object",
52
+ "properties": { "kind": { "const": "alias" } },
53
+ "required": ["redirectTo"]
54
+ }
55
+ }
56
+ ],
57
+ "$defs": {
58
+ "identifier": {
59
+ "type": "string",
60
+ "pattern": "^[a-z0-9](?:[a-z0-9._-]{0,126}[a-z0-9])?$"
61
+ },
62
+ "normalizedPath": {
63
+ "type": "string",
64
+ "not": { "type": "string", "pattern": "^/(?:%252[Ee]){1,2}(?:/|$)" },
65
+ "pattern": "^/(?!(?:\\.{1,2})(?:/|$))(?!.*/\\.{1,2}(?:/|$))(?!.*%25(?:0[0-9A-Fa-f]|1[0-9A-Fa-f]|2[Ff]|5[Cc]|7[Ff]))(?!.*\/(?:%252[Ee]){1,2}(?:/|$))(?:(?:[A-Za-z0-9._!~*'()-]|%(?:20|2[2-6BC]|3[A-F]|40|5[BDE]|60|7[B-D])|%(?:C[2-9A-F]|D[0-9A-F])%(?:[89AB][0-9A-F])|%E0%(?:[AB][0-9A-F])%(?:[89AB][0-9A-F])|%E[1-9A-CEF]%(?:[89AB][0-9A-F])%(?:[89AB][0-9A-F])|%ED%(?:[89][0-9A-F])%(?:[89AB][0-9A-F])|%F0%(?:[9AB][0-9A-F])%(?:[89AB][0-9A-F])%(?:[89AB][0-9A-F])|%F[1-3]%(?:[89AB][0-9A-F])%(?:[89AB][0-9A-F])%(?:[89AB][0-9A-F])|%F4%8[0-9A-F]%(?:[89AB][0-9A-F])%(?:[89AB][0-9A-F]))+(?:/(?:[A-Za-z0-9._!~*'()-]|%(?:20|2[2-6BC]|3[A-F]|40|5[BDE]|60|7[B-D])|%(?:C[2-9A-F]|D[0-9A-F])%(?:[89AB][0-9A-F])|%E0%(?:[AB][0-9A-F])%(?:[89AB][0-9A-F])|%E[1-9A-CEF]%(?:[89AB][0-9A-F])%(?:[89AB][0-9A-F])|%ED%(?:[89][0-9A-F])%(?:[89AB][0-9A-F])|%F0%(?:[9AB][0-9A-F])%(?:[89AB][0-9A-F])%(?:[89AB][0-9A-F])|%F[1-3]%(?:[89AB][0-9A-F])%(?:[89AB][0-9A-F])%(?:[89AB][0-9A-F])|%F4%8[0-9A-F]%(?:[89AB][0-9A-F])%(?:[89AB][0-9A-F]))+)*)?$"
66
+ },
67
+ "mountPath": {
68
+ "allOf": [
69
+ { "$ref": "#/$defs/normalizedPath" },
70
+ { "type": "string", "pattern": "^/(?!(?:\\.well-known|__evidence|__preview|_astro|_style-guide|admin|api|apps|assets|auth|brand|capabilities|cockpit|collections|dashboard|dev|favicon\\.svg|health|js|llms\\.txt|platform|preview|products|robots\\.txt|saved|search|shared|sitemap\\.xml|style-guide|tenants)(?:/|$))" }
71
+ ]
72
+ },
73
+ "aliasPath": {
74
+ "allOf": [
75
+ { "$ref": "#/$defs/mountPath" },
76
+ { "type": "string", "pattern": "^/.+" }
77
+ ]
78
+ }
79
+ }
80
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://tokenoftrust.com/schemas/publication-space/v1/ref.schema.json",
4
+ "title": "PublicationSpaceRefV1",
5
+ "type": "object",
6
+ "patternProperties": { "^\\$(?:schema|comment|id)$": {} },
7
+ "additionalProperties": false,
8
+ "required": ["version", "tenant", "spaceId"],
9
+ "properties": {
10
+ "version": { "const": 1 },
11
+ "tenant": {
12
+ "type": "string",
13
+ "pattern": "^[a-z0-9](?:[a-z0-9._-]{0,126}[a-z0-9])?$"
14
+ },
15
+ "spaceId": {
16
+ "type": "string",
17
+ "pattern": "^[a-z0-9](?:[a-z0-9._-]{0,126}[a-z0-9])?$"
18
+ }
19
+ }
20
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://tokenoftrust.com/schemas/publication-version/v1/pointer.schema.json",
4
+ "title": "PublicationChannelPointerV1",
5
+ "type": "object",
6
+ "patternProperties": { "^\\$(?:schema|comment|id)$": {} },
7
+ "additionalProperties": false,
8
+ "required": ["schemaVersion", "tenant", "spaceId", "channel", "revision", "versionId", "sourceSha", "artifactDigest", "updatedAt"],
9
+ "properties": {
10
+ "schemaVersion": { "const": 1 },
11
+ "tenant": { "$ref": "#/$defs/identifier" },
12
+ "spaceId": { "$ref": "#/$defs/identifier" },
13
+ "channel": { "enum": ["preview", "live"] },
14
+ "revision": { "type": "integer", "minimum": 1 },
15
+ "versionId": { "$ref": "#/$defs/versionId" },
16
+ "sourceSha": { "$ref": "#/$defs/sha40" },
17
+ "artifactDigest": { "$ref": "#/$defs/sha256" },
18
+ "updatedAt": { "$ref": "#/$defs/instant" }
19
+ },
20
+ "$defs": {
21
+ "identifier": { "type": "string", "pattern": "^[a-z0-9](?:[a-z0-9._-]{0,126}[a-z0-9])?$" },
22
+ "opaqueId": { "type": "string", "pattern": "^[a-z0-9](?:[a-z0-9._:-]{6,126}[a-z0-9])$" },
23
+ "versionId": { "type": "string", "pattern": "^pv_[a-z0-9](?:[a-z0-9._:-]{4,122}[a-z0-9])$" },
24
+ "sha40": { "type": "string", "pattern": "^[0-9a-f]{40}$" },
25
+ "sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
26
+ "instant": { "type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]{3}Z$" }
27
+ }
28
+ }
@@ -0,0 +1,44 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://tokenoftrust.com/schemas/publication-version/v1/transition-request.schema.json",
4
+ "title": "PublicationTransitionRequestV1",
5
+ "type": "object",
6
+ "patternProperties": { "^\\$(?:schema|comment|id)$": {} },
7
+ "additionalProperties": false,
8
+ "required": [
9
+ "schemaVersion",
10
+ "transitionId",
11
+ "operation",
12
+ "tenant",
13
+ "spaceId",
14
+ "channel",
15
+ "targetVersionId",
16
+ "expectedSourceSha",
17
+ "expectedArtifactDigest",
18
+ "expectedRevision",
19
+ "principal",
20
+ "occurredAt"
21
+ ],
22
+ "properties": {
23
+ "schemaVersion": { "const": 1 },
24
+ "transitionId": { "$ref": "#/$defs/opaqueId" },
25
+ "operation": { "enum": ["activate", "rollback"] },
26
+ "tenant": { "$ref": "#/$defs/identifier" },
27
+ "spaceId": { "$ref": "#/$defs/identifier" },
28
+ "channel": { "enum": ["preview", "live"] },
29
+ "targetVersionId": { "$ref": "#/$defs/versionId" },
30
+ "expectedSourceSha": { "$ref": "#/$defs/sha40" },
31
+ "expectedArtifactDigest": { "$ref": "#/$defs/sha256" },
32
+ "expectedRevision": { "type": "integer", "minimum": 0 },
33
+ "principal": { "$ref": "#/$defs/opaqueId" },
34
+ "occurredAt": { "$ref": "#/$defs/instant" }
35
+ },
36
+ "$defs": {
37
+ "identifier": { "type": "string", "pattern": "^[a-z0-9](?:[a-z0-9._-]{0,126}[a-z0-9])?$" },
38
+ "opaqueId": { "type": "string", "pattern": "^[a-z0-9](?:[a-z0-9._:-]{6,126}[a-z0-9])$" },
39
+ "versionId": { "type": "string", "pattern": "^pv_[a-z0-9](?:[a-z0-9._:-]{4,122}[a-z0-9])$" },
40
+ "sha40": { "type": "string", "pattern": "^[0-9a-f]{40}$" },
41
+ "sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
42
+ "instant": { "type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]{3}Z$" }
43
+ }
44
+ }
@@ -0,0 +1,47 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://tokenoftrust.com/schemas/publication-version/v1/transition.schema.json",
4
+ "title": "PublicationPointerTransitionV1",
5
+ "type": "object",
6
+ "patternProperties": { "^\\$(?:schema|comment|id)$": {} },
7
+ "additionalProperties": false,
8
+ "required": ["schemaVersion", "transitionId", "operation", "tenant", "spaceId", "channel", "previous", "next", "principal", "occurredAt"],
9
+ "properties": {
10
+ "schemaVersion": { "const": 1 },
11
+ "transitionId": { "$ref": "#/$defs/opaqueId" },
12
+ "operation": { "enum": ["activate", "rollback"] },
13
+ "tenant": { "$ref": "#/$defs/identifier" },
14
+ "spaceId": { "$ref": "#/$defs/identifier" },
15
+ "channel": { "enum": ["preview", "live"] },
16
+ "previous": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/snapshot" }] },
17
+ "next": { "$ref": "#/$defs/snapshot" },
18
+ "principal": { "$ref": "#/$defs/opaqueId" },
19
+ "occurredAt": { "$ref": "#/$defs/instant" }
20
+ },
21
+ "allOf": [
22
+ {
23
+ "if": { "properties": { "operation": { "const": "rollback" } }, "required": ["operation"] },
24
+ "then": { "properties": { "previous": { "$ref": "#/$defs/snapshot" } } }
25
+ }
26
+ ],
27
+ "$defs": {
28
+ "identifier": { "type": "string", "pattern": "^[a-z0-9](?:[a-z0-9._-]{0,126}[a-z0-9])?$" },
29
+ "opaqueId": { "type": "string", "pattern": "^[a-z0-9](?:[a-z0-9._:-]{6,126}[a-z0-9])$" },
30
+ "versionId": { "type": "string", "pattern": "^pv_[a-z0-9](?:[a-z0-9._:-]{4,122}[a-z0-9])$" },
31
+ "sha40": { "type": "string", "pattern": "^[0-9a-f]{40}$" },
32
+ "sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
33
+ "instant": { "type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]{3}Z$" },
34
+ "snapshot": {
35
+ "type": "object",
36
+ "patternProperties": { "^\\$(?:schema|comment|id)$": {} },
37
+ "additionalProperties": false,
38
+ "required": ["revision", "versionId", "sourceSha", "artifactDigest"],
39
+ "properties": {
40
+ "revision": { "type": "integer", "minimum": 1 },
41
+ "versionId": { "$ref": "#/$defs/versionId" },
42
+ "sourceSha": { "$ref": "#/$defs/sha40" },
43
+ "artifactDigest": { "$ref": "#/$defs/sha256" }
44
+ }
45
+ }
46
+ }
47
+ }
@@ -0,0 +1,58 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://tokenoftrust.com/schemas/publication-version/v1/version.schema.json",
4
+ "title": "PublicationVersionV1",
5
+ "type": "object",
6
+ "patternProperties": { "^\\$(?:schema|comment|id)$": {} },
7
+ "additionalProperties": false,
8
+ "required": ["schemaVersion", "versionId", "tenant", "spaceId", "source", "renderer", "artifactDigest", "createdAt", "metadata"],
9
+ "properties": {
10
+ "schemaVersion": { "const": 1 },
11
+ "versionId": { "$ref": "#/$defs/versionId" },
12
+ "tenant": { "$ref": "#/$defs/identifier" },
13
+ "spaceId": { "$ref": "#/$defs/identifier" },
14
+ "source": {
15
+ "type": "object",
16
+ "patternProperties": { "^\\$(?:schema|comment|id)$": {} },
17
+ "additionalProperties": false,
18
+ "required": ["forge", "repo", "commitSha"],
19
+ "properties": {
20
+ "forge": { "enum": ["gitea", "github", "fixture"] },
21
+ "repo": {
22
+ "type": "string",
23
+ "minLength": 1,
24
+ "maxLength": 256,
25
+ "pattern": "^(?!.*\\.\\.)(?!.*//)[A-Za-z0-9](?:[A-Za-z0-9._/-]{0,254}[A-Za-z0-9])?$"
26
+ },
27
+ "commitSha": { "$ref": "#/$defs/sha40" }
28
+ }
29
+ },
30
+ "renderer": {
31
+ "type": "object",
32
+ "patternProperties": { "^\\$(?:schema|comment|id)$": {} },
33
+ "additionalProperties": false,
34
+ "required": ["contractVersion", "themeContractVersion"],
35
+ "properties": {
36
+ "contractVersion": { "type": "string", "minLength": 1 },
37
+ "themeContractVersion": { "type": "string", "minLength": 1 }
38
+ }
39
+ },
40
+ "artifactDigest": { "$ref": "#/$defs/sha256" },
41
+ "createdAt": { "$ref": "#/$defs/instant" },
42
+ "metadata": {
43
+ "type": "object",
44
+ "patternProperties": { "^\\$(?:schema|comment|id)$": {} },
45
+ "additionalProperties": false,
46
+ "required": ["buildId"],
47
+ "properties": { "buildId": { "$ref": "#/$defs/opaqueId" } }
48
+ }
49
+ },
50
+ "$defs": {
51
+ "identifier": { "type": "string", "pattern": "^[a-z0-9](?:[a-z0-9._-]{0,126}[a-z0-9])?$" },
52
+ "opaqueId": { "type": "string", "pattern": "^[a-z0-9](?:[a-z0-9._:-]{6,126}[a-z0-9])$" },
53
+ "versionId": { "type": "string", "pattern": "^pv_[a-z0-9](?:[a-z0-9._:-]{4,122}[a-z0-9])$" },
54
+ "sha40": { "type": "string", "pattern": "^[0-9a-f]{40}$" },
55
+ "sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
56
+ "instant": { "type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]{3}Z$" }
57
+ }
58
+ }
@@ -98,7 +98,7 @@ export const ACTION_CATALOG = {
98
98
  },
99
99
  "cli.command.result": {
100
100
  actors: ["dev", "agent"], source: "cli", sinks: HIGH_VOLUME,
101
- argsAllow: ["command", "subcommand", "cliVersion", "exitCode", "durationMs"], renderedAllow: [],
101
+ argsAllow: ["command", "subcommand", "cliVersion", "exitCode", "durationMs", "diagnosticId"], renderedAllow: [],
102
102
  desc: "A `tot` CLI command finished (exit code + duration).",
103
103
  },
104
104
  "cli.obstacle.reported": {
@@ -122,6 +122,12 @@ export interface ReviewEnvironment {
122
122
  * surfaced in the PR review console. Absent/empty ⇒ validated clean.
123
123
  */
124
124
  findings?: PreviewStateFinding[];
125
+ /**
126
+ * Artifact paths this candidate's reconcile DROPPED from the version it published.
127
+ * Non-empty on a `ready` candidate means the preview renders the tenant's content
128
+ * MINUS these files; `lastError` names them in prose. Absent/empty ⇒ published clean.
129
+ */
130
+ droppedArtifacts?: string[];
125
131
  /** Auditable safety-block override applied to this candidate (who/why), if any. */
126
132
  overriddenBy?: PreviewStateOverride | null;
127
133
  /**
@@ -76,6 +76,14 @@ export interface PreviewState {
76
76
  * Absent/empty ⇒ the tenant's files validated clean. Written by `reconcilePreview`.
77
77
  */
78
78
  findings?: PreviewStateFinding[];
79
+ /**
80
+ * Artifact paths the last reconcile DROPPED from the version it published. A
81
+ * non-empty list on a SUCCESSFUL reconcile means the site is serving the tenant's
82
+ * content MINUS these files — they exist in the repo and are absent from the live
83
+ * version. Absent/empty ⇒ everything mapped was published. `lastError` names the
84
+ * same paths in prose. Written by `reconcilePreview`.
85
+ */
86
+ droppedArtifacts?: string[];
79
87
  /**
80
88
  * The auditable safety-block override applied to this reconcile (who/why), when a
81
89
  * blocking-safety finding was materialized past. Absent/null ⇒ no override.
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Route-document HTML cache policy (ADR 0013 — `serving.htmlCachePolicy`).
3
+ *
4
+ * The browser/shared TTLs a tenant's ROUTE DOCUMENTS (HTML) are served with are a
5
+ * declared property of the TENANT, read by BOTH public-serving substrates (the
6
+ * Cloudflare Worker+R2 pointer plane and the AWS S3/CloudFront plane), so moving
7
+ * substrate never silently changes repeat-visit caching. This module is the ONE
8
+ * place the policy is turned into a `Cache-Control` string, so both planes emit a
9
+ * byte-identical header from one formatter.
10
+ */
11
+
12
+ /** The declared route-document cache TTLs (all in SECONDS). Absent fields fall to {@link DEFAULT_HTML_CACHE_POLICY}. */
13
+ export interface HtmlCachePolicy {
14
+ /** `max-age` — how long a browser may reuse a route document without revalidating. */
15
+ browserMaxAge?: number;
16
+ /** `s-maxage` — how long the shared CDN cache may reuse it. */
17
+ sharedMaxAge?: number;
18
+ /** `stale-while-revalidate` — grace window a stale document may still serve while a fresh one is fetched. */
19
+ staleWhileRevalidate?: number;
20
+ }
21
+
22
+ /**
23
+ * The route-document default when a tenant declares no `serving.htmlCachePolicy`.
24
+ * A 5-minute browser+shared TTL with a 1-day SWR: fresh-biased because the pointer
25
+ * flip republishes at a STABLE url and every publish busts the edge (digest-scoped
26
+ * keys self-invalidate), so a short browser ceiling is safe and the ADR's contract.
27
+ */
28
+ export const DEFAULT_HTML_CACHE_POLICY: Required<HtmlCachePolicy> = {
29
+ browserMaxAge: 300,
30
+ sharedMaxAge: 300,
31
+ staleWhileRevalidate: 86400,
32
+ };
33
+
34
+ /**
35
+ * Render a {@link HtmlCachePolicy} to a `Cache-Control` header value. Each field
36
+ * falls back to {@link DEFAULT_HTML_CACHE_POLICY} INDEPENDENTLY, so a partial policy
37
+ * is completed rather than rejected, and `null`/`undefined` yields the full default.
38
+ * This is the single source of the route-document Cache-Control string for both planes.
39
+ */
40
+ export function formatHtmlCacheControl(policy?: HtmlCachePolicy | null): string {
41
+ const browserMaxAge = policy?.browserMaxAge ?? DEFAULT_HTML_CACHE_POLICY.browserMaxAge;
42
+ const sharedMaxAge = policy?.sharedMaxAge ?? DEFAULT_HTML_CACHE_POLICY.sharedMaxAge;
43
+ const staleWhileRevalidate =
44
+ policy?.staleWhileRevalidate ?? DEFAULT_HTML_CACHE_POLICY.staleWhileRevalidate;
45
+ return `public, max-age=${browserMaxAge}, s-maxage=${sharedMaxAge}, stale-while-revalidate=${staleWhileRevalidate}`;
46
+ }
47
+
48
+ /**
49
+ * The internal, MATERIALIZE-ONLY response header the render emits (gated on the
50
+ * materialize probe request header) so the publish/materialize plane can capture the
51
+ * tenant's resolved route-document Cache-Control into the bundle manifest — the same
52
+ * capture pattern as CSP. It is NEVER emitted on a real public response.
53
+ */
54
+ export const HTML_CACHE_POLICY_CAPTURE_HEADER = "x-tot-html-cache-policy";
55
+
56
+ /** The request header the materialize probe sends to ask the render to emit {@link HTML_CACHE_POLICY_CAPTURE_HEADER}. */
57
+ export const HTML_CACHE_POLICY_CAPTURE_PROBE = "x-tot-materialize-capture";
@@ -15,6 +15,14 @@
15
15
  // preview / script types the renderer needs. Read/apply only.
16
16
  export * from "./product.js";
17
17
  export * from "./tenant.js";
18
+ export * from "./publication-space.js";
19
+ export * from "./publication-routing.js";
20
+ export * from "./publication-version.js";
21
+ export * from "./publication-artifact.js";
22
+ export * from "./publication-reader.js";
23
+ // The ONE route-tier authority: route -> mount -> publication space ->
24
+ // {visibility, authorization} -> an ADR 0013 tier. No consumer derives its own.
25
+ export * from "./route-tier.js";
18
26
  export * from "./checkout.js";
19
27
  export * from "./membership.js";
20
28
  export * from "./checkout-orders.js";
@@ -51,6 +59,7 @@ export * from "./review-trust-proof.js";
51
59
  export * from "./compliance/index.js";
52
60
  export * from "./tenant-assets.js";
53
61
  export * from "./static-bundle.js";
62
+ export * from "./html-cache-policy.js";
54
63
  export * from "./binary-path.js";
55
64
  export * from "./hot-standby-readiness.js";
56
65
  export * from "./hash.js";