@tokenoftrust/storefront-runner 1.4.0 → 1.4.2-rc.0
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/apps/storefront/astro.config.mjs +17 -1
- package/apps/storefront/integrations/materialize-guard.mjs +56 -0
- package/apps/storefront/migrations-apps/0001_woozy_lyja.sql +22 -0
- package/apps/storefront/migrations-apps/0002_good_switch.sql +26 -0
- package/apps/storefront/migrations-apps/0003_mute_marauders.sql +12 -0
- package/apps/storefront/migrations-apps/meta/0001_snapshot.json +990 -0
- package/apps/storefront/migrations-apps/meta/0002_snapshot.json +1160 -0
- package/apps/storefront/migrations-apps/meta/0003_snapshot.json +1235 -0
- package/apps/storefront/migrations-apps/meta/_journal.json +21 -0
- package/apps/storefront/package.json +0 -1
- package/apps/storefront/public/js/dashboard-team.js +38 -2
- package/apps/storefront/src/components/Seo.astro +65 -1
- package/apps/storefront/src/components/admin/AdminBlogDetailRail.astro +878 -0
- package/apps/storefront/src/components/admin/AdminBlogTab.astro +1432 -0
- package/apps/storefront/src/components/admin/AdminCustomersTab.astro +3 -7
- package/apps/storefront/src/components/admin/AdminPublishTab.astro +1756 -1382
- package/apps/storefront/src/components/admin/AdminSubscriptionsTab.astro +1 -3
- package/apps/storefront/src/components/blog/BlogPaywall.astro +87 -0
- package/apps/storefront/src/components/blog/PostAccessBadge.astro +43 -0
- package/apps/storefront/src/components/blog/PostGrid.astro +57 -0
- package/apps/storefront/src/components/blog/ReactionBar.astro +214 -0
- package/apps/storefront/src/layouts/Layout.astro +48 -3
- package/apps/storefront/src/lib/activity/alerts.ts +426 -0
- package/apps/storefront/src/lib/activity/changeActorAttribution.ts +85 -0
- package/apps/storefront/src/lib/activity/deployVersion.ts +120 -0
- package/apps/storefront/src/lib/activity/ingest.ts +188 -0
- package/apps/storefront/src/lib/activity/ingestAuth.ts +105 -0
- package/apps/storefront/src/lib/activity/killSwitch.ts +80 -0
- package/apps/storefront/src/lib/activity/query.ts +403 -0
- package/apps/storefront/src/lib/activity/recordActivity.ts +101 -0
- package/apps/storefront/src/lib/activity/store.ts +120 -0
- package/apps/storefront/src/lib/activity/uiActor.ts +150 -0
- package/apps/storefront/src/lib/activity/workerCommit.ts +70 -0
- package/apps/storefront/src/lib/admin/adminShell.ts +290 -0
- package/apps/storefront/src/lib/admin/ai/approvalMode.ts +2 -3
- package/apps/storefront/src/lib/admin/ai/audit.ts +3 -5
- package/apps/storefront/src/lib/admin/checkoutStyleInput.ts +7 -7
- package/apps/storefront/src/lib/admin/checkoutStyleTarget.ts +3 -3
- package/apps/storefront/src/lib/admin/orderClient.ts +3 -5
- package/apps/storefront/src/lib/admin/services/orders.ts +17 -19
- package/apps/storefront/src/lib/admin/viewmodels/aiWorkflows.ts +4 -6
- package/apps/storefront/src/lib/admin/viewmodels/settings.ts +1 -1
- package/apps/storefront/src/lib/apps/adminService.ts +4 -4
- package/apps/storefront/src/lib/apps/adminSession.ts +53 -44
- package/apps/storefront/src/lib/apps/apiAuth.ts +2 -2
- package/apps/storefront/src/lib/apps/apiRoute.ts +2 -2
- package/apps/storefront/src/lib/apps/catalogMapper.ts +1 -1
- package/apps/storefront/src/lib/apps/credentials.ts +2 -2
- package/apps/storefront/src/lib/apps/gatewayKeys.ts +4 -4
- package/apps/storefront/src/lib/apps/healthAggregate.ts +5 -5
- package/apps/storefront/src/lib/apps/orders/attributionService.ts +2 -2
- package/apps/storefront/src/lib/apps/orders/customerHash.ts +1 -1
- package/apps/storefront/src/lib/apps/orders/foxyOrderClient.ts +12 -12
- package/apps/storefront/src/lib/apps/orders/idempotency.ts +7 -7
- package/apps/storefront/src/lib/apps/orders/orderForwardReceiver.ts +1 -1
- package/apps/storefront/src/lib/apps/orders/orderMapper.ts +2 -2
- package/apps/storefront/src/lib/apps/orders/ordersStore.ts +6 -6
- package/apps/storefront/src/lib/apps/registryService.ts +6 -6
- package/apps/storefront/src/lib/apps/scopes.ts +2 -2
- package/apps/storefront/src/lib/apps/tokenIssuer.ts +4 -4
- package/apps/storefront/src/lib/apps/tokenVerifier.ts +6 -6
- package/apps/storefront/src/lib/apps/widgets/eligibility.ts +2 -2
- package/apps/storefront/src/lib/apps/widgets/frameProps.ts +3 -3
- package/apps/storefront/src/lib/apps/widgets/launchToken.ts +4 -4
- package/apps/storefront/src/lib/apps/widgets/placements.ts +2 -2
- package/apps/storefront/src/lib/apps/widgets/renderSlot.ts +1 -1
- package/apps/storefront/src/lib/auth/adminEntry.ts +9 -9
- package/apps/storefront/src/lib/auth/identityToken.ts +6 -14
- package/apps/storefront/src/lib/auth/loginGate.ts +75 -13
- package/apps/storefront/src/lib/auth/mcpClientAssertion.ts +6 -4
- package/apps/storefront/src/lib/auth/operatorSession.ts +113 -0
- package/apps/storefront/src/lib/auth/route.ts +44 -4
- package/apps/storefront/src/lib/auth/session.ts +7 -8
- package/apps/storefront/src/lib/auth/totAccessClient.ts +8 -18
- package/apps/storefront/src/lib/basePath.ts +9 -2
- package/apps/storefront/src/lib/blog/access.ts +29 -0
- package/apps/storefront/src/lib/blog/collection.ts +313 -0
- package/apps/storefront/src/lib/blog/markdown.ts +174 -0
- package/apps/storefront/src/lib/blog/provider.ts +5 -0
- package/apps/storefront/src/lib/blog/reactions.ts +87 -0
- package/apps/storefront/src/lib/blog/rss.ts +92 -0
- package/apps/storefront/src/lib/blog/teaser.ts +83 -0
- package/apps/storefront/src/lib/blog/types.ts +34 -0
- package/apps/storefront/src/lib/blog/viewCounts.ts +243 -0
- package/apps/storefront/src/lib/d1/catalog.ts +2 -2
- package/apps/storefront/src/lib/d1/schema-apps.ts +147 -14
- package/apps/storefront/src/lib/dev/activityIngestToken.ts +2 -4
- package/apps/storefront/src/lib/dev/activityStore.ts +3 -5
- package/apps/storefront/src/lib/dev/apiBase.ts +1 -4
- package/apps/storefront/src/lib/dev/cockpitStore.ts +1 -9
- package/apps/storefront/src/lib/dev/devDraft.ts +1 -1
- package/apps/storefront/src/lib/dev/previewStatus.ts +9 -21
- package/apps/storefront/src/lib/dev/rendezvousBroker.ts +9 -24
- package/apps/storefront/src/lib/edgeCache.ts +17 -0
- package/apps/storefront/src/lib/env.ts +51 -0
- package/apps/storefront/src/lib/http/fetchTransport.ts +63 -0
- package/apps/storefront/src/lib/i18n.ts +25 -0
- package/apps/storefront/src/lib/jsonld.ts +118 -0
- package/apps/storefront/src/lib/monitoring/manifest.ts +11 -11
- package/apps/storefront/src/lib/newsletter/confirmationEmail.ts +30 -0
- package/apps/storefront/src/lib/newsletter/consent.ts +23 -0
- package/apps/storefront/src/lib/newsletter/digest.ts +117 -0
- package/apps/storefront/src/lib/newsletter/resendClient.ts +79 -0
- package/apps/storefront/src/lib/newsletter/send.ts +265 -0
- package/apps/storefront/src/lib/newsletter/subscribers.ts +156 -0
- package/apps/storefront/src/lib/publish/adminPublishTab.ts +3519 -0
- package/apps/storefront/src/lib/publish/apex-readiness.ts +41 -18
- package/apps/storefront/src/lib/publish/dispatchHealth.ts +5 -7
- package/apps/storefront/src/lib/publish/domainState.ts +22 -13
- package/apps/storefront/src/lib/publish/panelPolling.ts +78 -0
- package/apps/storefront/src/lib/publish/shipWorkspace.ts +100 -42
- package/apps/storefront/src/lib/publish/stageBundleUpload.ts +215 -0
- package/apps/storefront/src/lib/rate/kvWindow.ts +53 -0
- package/apps/storefront/src/lib/search/index.ts +2 -2
- package/apps/storefront/src/lib/seo/alternates.ts +42 -0
- package/apps/storefront/src/lib/seo/meta.ts +65 -0
- package/apps/storefront/src/lib/social/golive.ts +212 -0
- package/apps/storefront/src/lib/social/notify.ts +32 -0
- package/apps/storefront/src/lib/social/tokenStore.ts +171 -0
- package/apps/storefront/src/lib/the-build/provider.ts +27 -0
- package/apps/storefront/src/lib/the-build/readingTime.ts +35 -0
- package/apps/storefront/src/lib/the-build/toc.ts +95 -0
- package/apps/storefront/src/lib/tot/ToTClient.ts +1 -1
- package/apps/storefront/src/lib/tot/d1Client.ts +2 -2
- package/apps/storefront/src/lib/tot/totClientInterface.ts +3 -4
- package/apps/storefront/src/lib/webhooks/deliveryStore.ts +16 -17
- package/apps/storefront/src/middleware/index.ts +130 -2
- package/apps/storefront/src/pages/admin/ops-timeline.astro +420 -0
- package/apps/storefront/src/pages/admin.astro +52 -1206
- package/apps/storefront/src/pages/api/activity.ts +137 -0
- package/apps/storefront/src/pages/api/admin/activity-alerts.ts +73 -0
- package/apps/storefront/src/pages/api/apps/admin/credentials/rotate.ts +27 -1
- package/apps/storefront/src/pages/api/apps/admin/install.ts +26 -1
- package/apps/storefront/src/pages/api/apps/admin/resume.ts +24 -1
- package/apps/storefront/src/pages/api/apps/admin/suspend.ts +24 -1
- package/apps/storefront/src/pages/api/apps/admin/uninstall.ts +25 -1
- package/apps/storefront/src/pages/api/apps/admin/update.ts +24 -1
- package/apps/storefront/src/pages/api/apps/admin/webhooks/deliveries/[deliveryId]/replay.ts +11 -0
- package/apps/storefront/src/pages/api/apps/internal/order-forward.ts +11 -0
- package/apps/storefront/src/pages/api/apps/v1/attribution.ts +20 -0
- package/apps/storefront/src/pages/api/apps/v1/webhooks/deliveries/[deliveryId]/replay.ts +12 -0
- package/apps/storefront/src/pages/api/blog/[collection]/[slug]/react.ts +104 -0
- package/apps/storefront/src/pages/api/cache-purge.ts +11 -0
- package/apps/storefront/src/pages/api/dashboard/enter-vendor.ts +30 -0
- package/apps/storefront/src/pages/api/newsletter/[collection]/subscribe.ts +146 -0
- package/apps/storefront/src/pages/api/newsletter/confirm.ts +75 -0
- package/apps/storefront/src/pages/api/newsletter/unsubscribe.ts +90 -0
- package/apps/storefront/src/pages/api/publish/stage-bundle.ts +70 -0
- package/apps/storefront/src/pages/api/rum/vitals.ts +21 -2
- package/apps/storefront/src/pages/auth/login.astro +5 -4
- package/apps/storefront/src/pages/blog/[slug].astro +96 -16
- package/apps/storefront/src/pages/blog/author/[author].astro +140 -0
- package/apps/storefront/src/pages/blog/category/[category].astro +67 -0
- package/apps/storefront/src/pages/blog/index.astro +2 -0
- package/apps/storefront/src/pages/blog/tag/[tag].astro +65 -0
- package/apps/storefront/src/pages/cockpit.astro +74 -12
- package/apps/storefront/src/pages/dashboard/[appDomain]/team.astro +15 -11
- package/apps/storefront/src/pages/search.astro +1 -1
- package/apps/storefront/src/pages/sitemap.xml.ts +20 -0
- package/apps/storefront/src/pages/the-build/[slug].astro +129 -0
- package/apps/storefront/src/pages/the-build/index.astro +146 -0
- package/apps/storefront/src/pages/the-build/rss.xml.ts +33 -0
- package/apps/storefront/src/styles/admin.css +1080 -0
- package/apps/storefront/tsconfig.json +5 -0
- package/package.json +1 -1
- package/packages/public-runtime/package.json +1 -0
- package/packages/public-runtime/src/activity/README.md +146 -0
- package/packages/public-runtime/src/activity/catalog.ts +553 -0
- package/packages/public-runtime/src/activity/event.ts +168 -0
- package/packages/public-runtime/src/activity/index.ts +16 -0
- package/packages/public-runtime/src/activity/redaction.ts +263 -0
- package/packages/public-runtime/src/candidate-index.ts +13 -0
- package/packages/public-runtime/src/catalog-d1.ts +1 -1
- package/packages/public-runtime/src/customization-preview.ts +25 -2
- package/packages/public-runtime/src/customization-runtime.ts +125 -3
- package/packages/public-runtime/src/customization-versioning.ts +10 -0
- package/packages/public-runtime/src/index.ts +7 -0
- package/packages/public-runtime/src/static-bundle.ts +357 -0
- package/packages/public-runtime/src/tenant.ts +36 -8
- package/scripts/build/copy-tenant-assets.mjs +14 -4
- package/scripts/dev/ai-edit.mjs +1 -1
- package/scripts/dev/checkout-watch.mjs +2 -2
- package/scripts/dev/file-browser.mjs +2 -4
- package/scripts/dev/file-writer.mjs +1 -1
- package/scripts/dev/git-status.mjs +2 -2
- package/scripts/dev/locate-handler.mjs +3 -3
- package/scripts/dev/port-check.mjs +3 -3
- package/scripts/dev/publish.mjs +5 -9
- package/scripts/dev/shot.mjs +1 -1
- package/scripts/dev/unified-diff.mjs +8 -3
- package/scripts/tot-dev.mjs +6 -9
- package/apps/storefront/src/lib/webhooks/signing.ts +0 -29
- package/apps/storefront/src/lib/webhooks/webhookSigningKey.ts +0 -146
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
{
|
|
2
|
+
// Unlike the packages/* configs (which extend the repo's ../../tsconfig.base.json),
|
|
3
|
+
// the storefront extends Astro's own preset: it wires up .astro type resolution
|
|
4
|
+
// (.astro/types.d.ts), Astro/Vite bundler module resolution, and the Preact JSX
|
|
5
|
+
// runtime the client islands compile against. verbatimModuleSyntax is turned off
|
|
6
|
+
// (the base sets it on) because the JSX/Preact + Astro compilation model needs it.
|
|
2
7
|
"extends": "astro/tsconfigs/strict",
|
|
3
8
|
"compilerOptions": {
|
|
4
9
|
"strict": true,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tokenoftrust/storefront-runner",
|
|
3
|
-
"version": "1.4.0",
|
|
3
|
+
"version": "1.4.2-rc.0",
|
|
4
4
|
"license": "SEE LICENSE IN LICENSE",
|
|
5
5
|
"description": "World-shareable storefront runner: multi-tenant renderer on Astro/Cloudflare. No control plane.",
|
|
6
6
|
"packageManager": "pnpm@11.9.0",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tot/public-runtime",
|
|
3
3
|
"version": "0.1.0",
|
|
4
|
+
"description": "Public, edge-shipped storefront runtime model — renderer-safe tenant/product/catalog types, the CSP builder, the customization read/apply runtime, and the activity-telemetry contract. Node-free and open-sourceable; bundles into the Cloudflare Worker and must not import @tot/private-controlplane.",
|
|
4
5
|
"private": true,
|
|
5
6
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
7
|
"type": "module",
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# Operational activity telemetry — the actor×action contract (card D0)
|
|
2
|
+
|
|
3
|
+
The foundation the D1–D8 cards build on. Everything here is **pure types + pure
|
|
4
|
+
functions** in `@tot/public-runtime` (the node-free, dependency-free edge base),
|
|
5
|
+
so the storefront server, the Cloudflare Worker edge bundle, and the CLI's JS
|
|
6
|
+
mirror can all consume it. Nothing here does I/O or picks a store — the store
|
|
7
|
+
**decision** and cost model live in the repo-root `DECISIONS.md` §8; the
|
|
8
|
+
per-action store **routing** lives on each catalog entry (`sinks`).
|
|
9
|
+
|
|
10
|
+
Files:
|
|
11
|
+
|
|
12
|
+
| File | What |
|
|
13
|
+
|------|------|
|
|
14
|
+
| `event.ts` | The `ActivityEvent` envelope, `ACTIVITY_SCHEMA_VERSION`, `newEventId()`. |
|
|
15
|
+
| `catalog.ts` | The allowlisted `ACTION_CATALOG` registry + `ActionKey` + guards. |
|
|
16
|
+
| `redaction.ts` | Default-deny redaction contract + `createActivityEvent()` (the safe constructor). |
|
|
17
|
+
|
|
18
|
+
## The envelope
|
|
19
|
+
|
|
20
|
+
One event says: **an ACTOR performed an ACTION, here is the OUTCOME**, scoped to
|
|
21
|
+
a tenant/change, from a source, at a time. The design invariant is a hard split
|
|
22
|
+
between two zones:
|
|
23
|
+
|
|
24
|
+
- **Core fields** (`v`, `id`, `at`, `actor`, `action`, `source`, `scope`,
|
|
25
|
+
`outcome`) — *always safe to store, never redacted*. They carry no free text
|
|
26
|
+
and no third-party PII **by construction**: `actor.id` is opaque, `action` is
|
|
27
|
+
an allowlisted catalog key, `outcome.errorClass` is a low-cardinality class
|
|
28
|
+
(never a raw message).
|
|
29
|
+
- **`payload`** (`args` + `rendered`) — the *extensible, always-redacted* zone.
|
|
30
|
+
Whatever a call site puts here is default-**denied**.
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
import { createActivityEvent } from "@tot/public-runtime";
|
|
34
|
+
|
|
35
|
+
const { event, report } = createActivityEvent({
|
|
36
|
+
action: "cli.command.result", // must be a catalog key (compile-checked)
|
|
37
|
+
actor: { kind: "dev", id: hashedDevId },
|
|
38
|
+
source: "cli",
|
|
39
|
+
scope: { tenantId, traceId },
|
|
40
|
+
outcome:{ status: "succeeded", durationMs: 812 },
|
|
41
|
+
payload:{ args: { command: "ship", cliVersion: "1.4.0", exitCode: 0,
|
|
42
|
+
secretToken: "…" } }, // ← dropped: not allowlisted / key canary
|
|
43
|
+
});
|
|
44
|
+
// event.payload.args === { command: "ship", cliVersion: "1.4.0", exitCode: 0 }
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
`createActivityEvent()` is the **only** sanctioned constructor: it fills
|
|
48
|
+
`v`/`id`/`at` and runs the raw payload through the redaction contract, so you
|
|
49
|
+
**cannot** produce an event whose payload skipped redaction.
|
|
50
|
+
|
|
51
|
+
## The action catalog
|
|
52
|
+
|
|
53
|
+
`action` is never a free string — it is a key of `ACTION_CATALOG`. Each entry
|
|
54
|
+
declares `actors` (who may emit it), `source`, `sinks` (store routing), and the
|
|
55
|
+
default-deny `argsAllow` / `renderedAllow` payload allowlists. Adding a new
|
|
56
|
+
action = a deliberate edit to `catalog.ts` (+ the CLI mirror, below), never an
|
|
57
|
+
ad-hoc string at a call site. This is what keeps the D5 query surface and the
|
|
58
|
+
D6/D7 alert rules tractable.
|
|
59
|
+
|
|
60
|
+
### The naming standard (two tiers)
|
|
61
|
+
|
|
62
|
+
Every key is dot-namespaced and its **first segment is a `<domain>`** — there are
|
|
63
|
+
**no un-namespaced keys**. The domain prefix is stable so dashboards and alert rules
|
|
64
|
+
can glob it (`change.*`, `preview.*`, …). Within that, the catalog uses **two shapes**,
|
|
65
|
+
chosen by whether the action is atomic or two-phase:
|
|
66
|
+
|
|
67
|
+
- **`<domain>.<verb>` (imperative)** — an **atomic** action that happens in one shot.
|
|
68
|
+
Examples: `change.ship`, `change.revert`, `change.go_live`, `grant.invite`,
|
|
69
|
+
`grant.revoke`, `store.connect`, `preview.override`.
|
|
70
|
+
- **`<domain>.<entity>.<verb|state>` (participle/state)** — a **two-phase / async**
|
|
71
|
+
action that **opens then closes** (an invoke/result pair, or a received→terminal span).
|
|
72
|
+
Examples: `cli.command.invoked` + `cli.command.result`, `preview.build.requested` +
|
|
73
|
+
`preview.build.completed`, `webhook.reconcile.received` + `reconcile.terminal`.
|
|
74
|
+
|
|
75
|
+
The **domain must be one of the closed set**: `cli`, `dev`, `preview`, `webhook`,
|
|
76
|
+
`reconcile`, `deploy`, `change`, `content`, `grant`, `store`, `app`, `agent`, `system`.
|
|
77
|
+
Adding a key with a new domain is a deliberate decision — widen this list here first.
|
|
78
|
+
|
|
79
|
+
**Two-phase pairing going forward:** a **new** two-phase action pairs `.invoked` /
|
|
80
|
+
`.result`. The pre-existing `.requested` / `.completed` (`preview.build.*`) and
|
|
81
|
+
`.received` / `.terminal` (`webhook.reconcile.received` + `reconcile.terminal`) pairs are
|
|
82
|
+
**grandfathered as-is — do not rename them** (`alerts.ts` hardcodes some of these literals,
|
|
83
|
+
so a rename would silently break the D7 detectors).
|
|
84
|
+
|
|
85
|
+
The initial catalog was reverse-engineered from the activity surfaces that **already
|
|
86
|
+
exist informally** in this repo (CLI dispatch + `~/.tot/activity.log`, the obstacle
|
|
87
|
+
beacon, the local→hosted dev bridge, preview/reconcile/webhook, deploy provenance, the
|
|
88
|
+
ShipLoop `CHANGE_STATES` + admin ship routes, app installs), so D1–D3 map onto it 1:1.
|
|
89
|
+
|
|
90
|
+
## The redaction contract (the D8 attack surface)
|
|
91
|
+
|
|
92
|
+
Applied to `payload` for every event, in order:
|
|
93
|
+
|
|
94
|
+
1. **Default-deny allowlist** — only the top-level keys named by the action's
|
|
95
|
+
`argsAllow`/`renderedAllow` are eligible. Everything else is **dropped**: not
|
|
96
|
+
stored, not logged, never "kept raw and redacted later".
|
|
97
|
+
2. **Primitive-only values** — an allowlisted value must be string/number/bool.
|
|
98
|
+
Objects/arrays are dropped (nested structures are where secrets hide; we do
|
|
99
|
+
not walk them). Structured args flatten into named primitive keys at the call
|
|
100
|
+
site.
|
|
101
|
+
3. **Canary scan** — allowlisted primitives are scanned for secret/PII **shapes**
|
|
102
|
+
(JWT, bearer, AWS/GitHub/Slack/OpenAI keys, private keys, email, card, phone,
|
|
103
|
+
high-entropy tokens) and secret-looking **key names** (`token`, `secret`,
|
|
104
|
+
`password`, `authorization`, …). A value hit → replaced with `«redacted»` and
|
|
105
|
+
reported (`report.canaryTripped`); a key-name hit → dropped outright.
|
|
106
|
+
|
|
107
|
+
The `RedactionReport` returned alongside the event carries **the fact of** each
|
|
108
|
+
drop/hit (lane, key, reason, canary label) — never the offending value. D4's
|
|
109
|
+
ingest logs it and emits `system.ingest.rejected` when a canary trips; D6/D7
|
|
110
|
+
alert on `canaryTripped`.
|
|
111
|
+
|
|
112
|
+
## Consuming this from the downstream cards
|
|
113
|
+
|
|
114
|
+
- **D1 server `recordActivity()`** — import `createActivityEvent`, build the
|
|
115
|
+
event, fan out to the sinks named on the action's `spec.sinks` (start with
|
|
116
|
+
`logs`; supersede the interim `apps/storefront/src/lib/activity/recordActivity.ts`
|
|
117
|
+
slice, whose `candidate.reject` becomes `change.reject`).
|
|
118
|
+
- **D2 deploy provenance** — emit `deploy.version_observed`.
|
|
119
|
+
- **D3 CLI `emitActivity`** — the CLI is **pure JS and does not import TS
|
|
120
|
+
packages** (it publishes to npm standalone and mirrors TS contracts with
|
|
121
|
+
keep-in-step tests, e.g. `no-gitea-links.test.mjs`). So D3 ships a small JS
|
|
122
|
+
mirror of the `ActionKey` list + the safe-constructor shape, plus a
|
|
123
|
+
keep-in-step test that fails the build if the mirror drifts from
|
|
124
|
+
`catalog.ts`. **Do not** make the CLI depend on `@tot/public-runtime`.
|
|
125
|
+
- **D4 ingest + store** — validate with `isActionKey` + `isActorAllowed`, run
|
|
126
|
+
`redactPayload` (belt-and-suspenders even though emitters already redacted),
|
|
127
|
+
route by `spec.sinks`. See `DECISIONS.md` §8 for the D1 table (`activity_events`
|
|
128
|
+
in `STOREFRONT_APPS_DB`, alongside the existing `app_audit_log`) and the
|
|
129
|
+
Analytics Engine binding to provision.
|
|
130
|
+
- **D5 query/timeline UI** — reads the `timeline`-sink rows from D1.
|
|
131
|
+
|
|
132
|
+
## Open questions deliberately left for downstream
|
|
133
|
+
|
|
134
|
+
- **Actor-id pseudonymization salt** (D1/D4). This module scrubs PII that leaks
|
|
135
|
+
into the *payload*, but `actor.id` in the core zone is the emitter's job to
|
|
136
|
+
pseudonymize. A shared salted non-reversible hash helper (salt as a Worker
|
|
137
|
+
secret) should land with D1/D4 — do **not** bake a weak unsalted hash into this
|
|
138
|
+
edge-shipped package.
|
|
139
|
+
- **Analytics Engine binding + D1 `activity_events` schema** (D4). Named in
|
|
140
|
+
`DECISIONS.md` §8; the actual `wrangler.toml` binding and the Drizzle migration
|
|
141
|
+
are D4's to write.
|
|
142
|
+
- **Retention/pruning job for the D1 timeline** (D4/D5). Arbitrary retention is
|
|
143
|
+
the reason the queryable cohort is in D1 not Analytics Engine; the pruning
|
|
144
|
+
cron is downstream.
|
|
145
|
+
- **Agent cohort payload** — `agent.action.*` keys are a placeholder spine with
|
|
146
|
+
minimal args until the agent-cohort card defines what an agent may record.
|