@littlebearapps/platform-admin-sdk 1.2.0 → 1.4.1

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/README.md CHANGED
@@ -4,6 +4,16 @@
4
4
 
5
5
  Generates workers, D1 migrations, and config files. Run once, then you own the code.
6
6
 
7
+ > **Using Claude Code?** Install the [Platform SDK Plugin](https://github.com/littlebearapps/platform-sdk-plugin) for automated SDK convention enforcement — it validates wrangler bindings, budget wrappers, and cost safety patterns in real time.
8
+
9
+ ## Prerequisites
10
+
11
+ - **Node.js 20+** and npm
12
+ - **wrangler CLI** installed and authenticated (`npx wrangler whoami`)
13
+ - **Cloudflare Workers Paid plan** (required for KV, Queues, and D1)
14
+ - **GitHub organisation** (Standard/Full tiers — for error collection GitHub issues)
15
+ - **Gatus instance** (optional — for heartbeat monitoring)
16
+
7
17
  ## Usage
8
18
 
9
19
  ```bash
@@ -17,9 +27,12 @@ The CLI prompts for:
17
27
  - **Gatus URL** (optional) — for heartbeat monitoring
18
28
  - **Default assignee** — GitHub username for error issues
19
29
 
20
- ### CLI Flags (non-interactive)
30
+ ### CLI Commands
31
+
32
+ #### `scaffold` (default)
21
33
 
22
34
  ```bash
35
+ npx @littlebearapps/platform-admin-sdk my-platform
23
36
  npx @littlebearapps/platform-admin-sdk my-platform --tier full --github-org myorg --skip-prompts
24
37
  ```
25
38
 
@@ -31,6 +44,27 @@ npx @littlebearapps/platform-admin-sdk my-platform --tier full --github-org myor
31
44
  | `--default-assignee <user>` | Default GitHub issue assignee |
32
45
  | `--skip-prompts` | Fail if required flags missing (for CI/automation) |
33
46
 
47
+ #### `upgrade`
48
+
49
+ ```bash
50
+ npx @littlebearapps/platform-admin-sdk upgrade
51
+ npx @littlebearapps/platform-admin-sdk upgrade --dry-run
52
+ npx @littlebearapps/platform-admin-sdk upgrade --tier standard
53
+ ```
54
+
55
+ | Flag | Description |
56
+ |------|------------|
57
+ | `--dry-run` | Preview changes without writing files |
58
+ | `--tier <tier>` | Upgrade to a higher tier |
59
+
60
+ #### `adopt`
61
+
62
+ ```bash
63
+ npx @littlebearapps/platform-admin-sdk adopt . --tier minimal --project-name my-platform --skip-prompts
64
+ ```
65
+
66
+ Creates a `.platform-scaffold.json` manifest for projects scaffolded before v1.1.0. See [Upgrade vs Adopt](#upgrade-vs-adopt).
67
+
34
68
  ## Tiers
35
69
 
36
70
  | Tier | Workers | What You Get | Est. Cost |
@@ -39,45 +73,63 @@ npx @littlebearapps/platform-admin-sdk my-platform --tier full --github-org myor
39
73
  | **Standard** | 3 | + Error collector (auto GitHub issues), gap detection sentinel | ~$0/mo |
40
74
  | **Full** | 8 | + AI pattern discovery, alert router, notifications, search, settings | ~$5/mo |
41
75
 
76
+ See [Tier Comparison](../../docs/admin-sdk/tiers.md) for a detailed breakdown of what each tier generates.
77
+
42
78
  ## What Gets Generated
43
79
 
44
80
  ### All tiers
45
81
 
46
82
  ```
47
83
  my-platform/
48
- +-- platform/config/
49
- | +-- services.yaml # Project registry, feature definitions
50
- | +-- budgets.yaml # Daily limits, circuit breaker thresholds
51
- +-- storage/d1/migrations/ # D1 schema (4 core migrations + seed)
52
- +-- workers/
53
- | +-- platform-usage.ts # Data warehouse worker (cron + queue consumer)
54
- | +-- lib/ # Shared libraries (billing, analytics, budgets)
55
- +-- scripts/
56
- | +-- sync-config.ts # Sync YAML config to D1/KV
57
- +-- wrangler.*.jsonc # Worker configs with binding placeholders
58
- +-- package.json
59
- +-- tsconfig.json
60
- +-- README.md
84
+ ├── platform/config/
85
+ ├── services.yaml # Project registry, feature definitions
86
+ └── budgets.yaml # Daily limits, circuit breaker thresholds
87
+ ├── storage/d1/migrations/ # D1 schema (4 core migrations + seed)
88
+ ├── workers/
89
+ ├── platform-usage.ts # Data warehouse worker (cron + queue consumer)
90
+ └── lib/ # Shared libraries (billing, analytics, budgets)
91
+ ├── docs/
92
+ └── kv-key-patterns.md # KV key prefix reference
93
+ ├── scripts/
94
+ │ └── sync-config.ts # Sync YAML config to D1/KV
95
+ ├── wrangler.*.jsonc # Worker configs with binding placeholders
96
+ ├── package.json
97
+ ├── tsconfig.json
98
+ └── README.md
61
99
  ```
62
100
 
101
+ ### Key generated files
102
+
103
+ | File | Purpose |
104
+ |------|---------|
105
+ | `platform/config/services.yaml` | Project registry — feature definitions, connections, metadata |
106
+ | `platform/config/budgets.yaml` | Daily limits, circuit breaker thresholds, warning percentages |
107
+ | `storage/d1/migrations/001_*.sql` | Core tables: project registry, resource snapshots, daily rollups |
108
+ | `workers/platform-usage.ts` | Central data warehouse — receives queue telemetry, stores in D1 |
109
+ | `scripts/sync-config.ts` | Syncs YAML config to D1 + KV (run after config changes) |
110
+
63
111
  ### Standard tier adds
64
112
 
65
- - `workers/error-collector.ts` Tail worker that creates GitHub issues from errors
66
- - `workers/platform-sentinel.ts` — Gap detection, cost monitoring, alerts
67
- - `workers/lib/error-collector/`Fingerprinting, deduplication, digest
68
- - `workers/lib/sentinel/` Project gap detection
69
- - `storage/d1/migrations/005_error_collection.sql`
113
+ | File | Purpose |
114
+ |------|---------|
115
+ | `workers/error-collector.ts` | Tail worker creates GitHub issues from worker errors |
116
+ | `workers/platform-sentinel.ts` | Gap detection, cost monitoring, alerts |
117
+ | `workers/lib/error-collector/` | Fingerprinting, deduplication, digest generation |
118
+ | `workers/lib/sentinel/` | Per-project gap detection |
119
+ | `storage/d1/migrations/005_error_collection.sql` | Error tables: occurrences, fingerprint decisions, digests |
70
120
 
71
121
  ### Full tier adds
72
122
 
73
- - `workers/pattern-discovery.ts` AI-assisted transient error pattern discovery
74
- - `workers/platform-alert-router.ts` — Unified alert normalisation and routing
75
- - `workers/platform-notifications.ts` In-app notification API
76
- - `workers/platform-search.ts` Full-text search (FTS5)
77
- - `workers/platform-settings.ts` Settings management API
78
- - `workers/lib/pattern-discovery/` Clustering, AI prompts, validation, shadow eval
79
- - `storage/d1/migrations/006_pattern_discovery.sql`
80
- - `storage/d1/migrations/007_notifications_search.sql`
123
+ | File | Purpose |
124
+ |------|---------|
125
+ | `workers/pattern-discovery.ts` | AI-assisted transient error pattern discovery |
126
+ | `workers/platform-alert-router.ts` | Unified alert normalisation and routing |
127
+ | `workers/platform-notifications.ts` | In-app notification API |
128
+ | `workers/platform-search.ts` | Full-text search (FTS5) |
129
+ | `workers/platform-settings.ts` | Settings management API |
130
+ | `workers/lib/pattern-discovery/` | Types, clustering, AI prompts, validation, shadow evaluation |
131
+ | `storage/d1/migrations/006_pattern_discovery.sql` | Pattern tables |
132
+ | `storage/d1/migrations/007_notifications_search.sql` | Notification and search tables |
81
133
 
82
134
  ## Post-Scaffold Steps
83
135
 
@@ -156,11 +208,24 @@ npx wrangler deploy -c wrangler.my-platform-pattern-discovery.jsonc
156
208
  npx wrangler deploy -c wrangler.my-platform-alert-router.jsonc
157
209
  ```
158
210
 
159
- ## Updating Your Platform
211
+ See [Quickstart Guide](../../docs/admin-sdk/quickstart.md) for a detailed walkthrough.
160
212
 
161
- Starting with v1.1.0, the Admin SDK writes a `.platform-scaffold.json` manifest that tracks what was generated. This enables safe, incremental upgrades. **Commit this file to git** — it's how the upgrade command knows what to update.
213
+ ## The Manifest File
214
+
215
+ When you scaffold or upgrade, the SDK writes a `.platform-scaffold.json` file. **Commit this to git** — it's how `upgrade` knows what to update.
216
+
217
+ The manifest contains:
218
+ - **`sdkVersion`** — Version of the Admin SDK that generated the files
219
+ - **`tier`** — Infrastructure tier (minimal/standard/full)
220
+ - **`context`** — Project name, slug, organisation, and other scaffold-time settings
221
+ - **`files`** — SHA-256 hash of each generated file as originally written
222
+ - **`highestScaffoldMigration`** — Highest D1 migration number generated
223
+
224
+ The `files` hash map is the basis for the three-way merge during `upgrade`: if your current disk content matches the original hash, the file is "unmodified" and can be safely updated. If the disk content differs, you've customised it and `upgrade` skips it with a warning.
225
+
226
+ ## Updating Your Platform
162
227
 
163
- ### Upgrade an existing project
228
+ ### Upgrade (v1.1.0+)
164
229
 
165
230
  ```bash
166
231
  cd my-platform
@@ -169,9 +234,9 @@ npx @littlebearapps/platform-admin-sdk upgrade
169
234
 
170
235
  The upgrade command:
171
236
  - **Creates** new files added in the SDK update
172
- - **Updates** files you haven't modified (compares content hashes)
173
- - **Skips** files you've customised (with a warning)
174
- - **Renumbers** new migrations to avoid conflicts with your own
237
+ - **Updates** files you haven't modified (compares content hashes from manifest)
238
+ - **Skips** files you've customised (with a warning showing which files were skipped)
239
+ - **Renumbers** new D1 migrations above your highest existing migration
175
240
 
176
241
  Preview changes without writing:
177
242
 
@@ -185,15 +250,22 @@ Upgrade to a higher tier:
185
250
  npx @littlebearapps/platform-admin-sdk upgrade --tier standard
186
251
  ```
187
252
 
188
- ### Adopt a pre-v1.1.0 project
253
+ ### Upgrade vs Adopt
189
254
 
190
- Projects scaffolded before v1.1.0 don't have a manifest. Run `adopt` first:
191
-
192
- ```bash
193
- npx @littlebearapps/platform-admin-sdk adopt . --tier minimal --project-name my-platform --skip-prompts
194
255
  ```
256
+ Do you have .platform-scaffold.json in your project?
257
+
258
+ ├── YES → Run: npx @littlebearapps/platform-admin-sdk upgrade
259
+ │ (three-way merge using manifest hashes)
260
+
261
+ └── NO → Run: npx @littlebearapps/platform-admin-sdk adopt . --tier <your-tier>
262
+ (creates manifest by hashing existing files as baseline)
263
+ Then run: npx @littlebearapps/platform-admin-sdk upgrade
264
+ ```
265
+
266
+ Projects scaffolded before v1.1.0 don't have a manifest. The `adopt` command hashes your existing SDK-generated files as the "original" state, creating a baseline for future upgrades.
195
267
 
196
- This hashes your existing files as a baseline and writes `.platform-scaffold.json`. You can then run `upgrade` normally.
268
+ See [Upgrade Guide](../../docs/admin-sdk/upgrade-guide.md) for detailed instructions.
197
269
 
198
270
  ## Data Safety
199
271
 
@@ -210,20 +282,43 @@ The scaffolder generates core infrastructure only. It does **not** create:
210
282
  - Email workers or notification templates
211
283
  - Data connectors (Stripe, GA4, Plausible, etc.)
212
284
  - Test suites
213
- - CI/CD workflows
285
+ - CI/CD workflows (use the [consumer-check.yml](../../docs/admin-sdk/ci-workflow.md) reusable workflow)
214
286
 
215
287
  These are project-specific — build them as you need them.
216
288
 
217
- ## Consumer SDK
289
+ ## Consumer SDK Integration
218
290
 
219
- The generated workers use `@littlebearapps/platform-consumer-sdk` — the Consumer SDK. Install it in your application workers to send telemetry to the platform backend:
291
+ The generated backend workers use `@littlebearapps/platform-consumer-sdk` internally. To connect your application workers, install the Consumer SDK and add the required bindings:
220
292
 
221
293
  ```bash
222
294
  npm install @littlebearapps/platform-consumer-sdk
223
295
  ```
224
296
 
225
- See the [Consumer SDK README](../consumer-sdk/README.md) for integration details.
297
+ Add to each application worker's `wrangler.jsonc`:
298
+
299
+ ```jsonc
300
+ {
301
+ "kv_namespaces": [
302
+ { "binding": "PLATFORM_CACHE", "id": "YOUR_KV_NAMESPACE_ID" }
303
+ ],
304
+ "queues": {
305
+ "producers": [
306
+ { "binding": "TELEMETRY_QUEUE", "queue": "my-platform-telemetry" }
307
+ ]
308
+ },
309
+ // Standard/Full tier — route errors to error-collector
310
+ "tail_consumers": [
311
+ { "service": "my-platform-error-collector" }
312
+ ]
313
+ }
314
+ ```
315
+
316
+ See the [Consumer SDK README](../consumer-sdk/README.md) for integration details and the [First Worker tutorial](../../docs/guides/first-worker.md) for a complete walkthrough.
317
+
318
+ ## Multi-Account Support
319
+
320
+ The Admin SDK's programmatic API accepts `accountId` and `apiToken` per call, enabling cross-account monitoring and emergency control from a single script or worker. See the [Multi-Account Setup guide](../../docs/guides/multi-account.md) for architecture patterns.
226
321
 
227
- ## License
322
+ ## Licence
228
323
 
229
- MIT
324
+ MIT — Made with ❤️ by [Little Bear Apps](https://littlebearapps.com) 🐶
@@ -6,7 +6,7 @@
6
6
  */
7
7
  import type { Tier } from './prompts.js';
8
8
  /** Single source of truth for the SDK version. */
9
- export declare const SDK_VERSION = "1.2.0";
9
+ export declare const SDK_VERSION = "1.4.1";
10
10
  /** Returns true if `to` is the same or higher tier than `from`. */
11
11
  export declare function isTierUpgradeOrSame(from: Tier, to: Tier): boolean;
12
12
  /** Check if a template file is a numbered migration (not seed.sql). */
package/dist/templates.js CHANGED
@@ -5,7 +5,7 @@
5
5
  * All other files are copied verbatim.
6
6
  */
7
7
  /** Single source of truth for the SDK version. */
8
- export const SDK_VERSION = '1.2.0';
8
+ export const SDK_VERSION = '1.4.1';
9
9
  /** Tier ordering for upgrade validation. */
10
10
  const TIER_ORDER = { minimal: 0, standard: 1, full: 2 };
11
11
  /** Returns true if `to` is the same or higher tier than `from`. */
@@ -82,6 +82,8 @@ const SHARED_FILES = [
82
82
  // Workers — lib/usage/collectors (pluggable interface + example)
83
83
  { src: 'shared/workers/lib/usage/collectors/index.ts', dest: 'workers/lib/usage/collectors/index.ts', template: false },
84
84
  { src: 'shared/workers/lib/usage/collectors/example.ts', dest: 'workers/lib/usage/collectors/example.ts', template: false },
85
+ // Documentation
86
+ { src: 'shared/docs/kv-key-patterns.md', dest: 'docs/kv-key-patterns.md', template: false },
85
87
  ];
86
88
  const STANDARD_FILES = [
87
89
  // Additional migrations
@@ -116,6 +118,7 @@ const FULL_FILES = [
116
118
  { src: 'full/wrangler.settings.jsonc.hbs', dest: 'wrangler.{{projectSlug}}-settings.jsonc', template: true },
117
119
  // Workers — pattern-discovery (AI-assisted transient error patterns)
118
120
  { src: 'full/workers/pattern-discovery.ts', dest: 'workers/pattern-discovery.ts', template: false },
121
+ { src: 'full/workers/lib/pattern-discovery/index.ts', dest: 'workers/lib/pattern-discovery/index.ts', template: false },
119
122
  { src: 'full/workers/lib/pattern-discovery/types.ts', dest: 'workers/lib/pattern-discovery/types.ts', template: false },
120
123
  { src: 'full/workers/lib/pattern-discovery/clustering.ts', dest: 'workers/lib/pattern-discovery/clustering.ts', template: false },
121
124
  { src: 'full/workers/lib/pattern-discovery/ai-prompt.ts', dest: 'workers/lib/pattern-discovery/ai-prompt.ts', template: false },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@littlebearapps/platform-admin-sdk",
3
- "version": "1.2.0",
3
+ "version": "1.4.1",
4
4
  "description": "Platform Admin SDK — scaffold backend infrastructure with workers, circuit breakers, and cost protection for Cloudflare",
5
5
  "type": "module",
6
6
  "bin": {
@@ -35,12 +35,22 @@
35
35
  "directory": "packages/admin-sdk"
36
36
  },
37
37
  "keywords": [
38
+ "cloudflare",
38
39
  "cloudflare-workers",
39
- "platform-admin-sdk",
40
40
  "scaffold",
41
41
  "cost-protection",
42
- "circuit-breaker"
42
+ "circuit-breaker",
43
+ "billing-safety",
44
+ "observability",
45
+ "telemetry",
46
+ "budget-enforcement",
47
+ "error-collection",
48
+ "usage-monitoring"
43
49
  ],
50
+ "homepage": "https://github.com/littlebearapps/platform-sdks#readme",
51
+ "bugs": {
52
+ "url": "https://github.com/littlebearapps/platform-sdks/issues"
53
+ },
44
54
  "author": "Little Bear Apps",
45
55
  "license": "MIT"
46
56
  }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Pattern Discovery Module
3
+ *
4
+ * AI-assisted discovery of transient error patterns.
5
+ *
6
+ * @module workers/lib/pattern-discovery
7
+ */
8
+
9
+ export * from './types';
10
+ export * from './clustering';
11
+ export * from './ai-prompt';
12
+ export * from './validation';
13
+ export * from './storage';
@@ -329,6 +329,7 @@ export async function refreshDynamicPatternsCache(
329
329
  FROM transient_pattern_suggestions
330
330
  WHERE status = 'approved'
331
331
  ORDER BY created_at ASC
332
+ LIMIT 500
332
333
  `
333
334
  )
334
335
  .all<PatternRule & { id: string }>();
@@ -0,0 +1,101 @@
1
+ # KV Key Patterns Reference
2
+
3
+ All keys stored in the `PLATFORM_CACHE` KV namespace, grouped by subsystem.
4
+
5
+ > Generated by `@littlebearapps/platform-admin-sdk`. Keep this up to date as you add features.
6
+
7
+ ---
8
+
9
+ ## Circuit Breaker State
10
+
11
+ | Key Pattern | Example | TTL | Worker | Purpose |
12
+ |---|---|---|---|---|
13
+ | `GLOBAL_STOP_ALL` | `GLOBAL_STOP_ALL` | None | platform-usage | Emergency kill switch — pauses all operations |
14
+ | `PROJECT:{slug}:STATUS` | `PROJECT:MY-APP:STATUS` | None | platform-usage | Per-project circuit breaker state (`active`/`warning`/`paused`) |
15
+ | `FEATURE:{key}:enabled` | `FEATURE:my-app:scanner:enabled` | None | platform-usage | Feature-level on/off flag |
16
+ | `FEATURE:{key}:disabled_reason` | `FEATURE:my-app:scanner:disabled_reason` | None | platform-usage | Why feature was disabled |
17
+ | `FEATURE:{key}:disabled_at` | `FEATURE:my-app:scanner:disabled_at` | None | platform-usage | Timestamp of disable |
18
+ | `FEATURE:{key}:auto_reset_at` | `FEATURE:my-app:scanner:auto_reset_at` | None | platform-usage | Auto-reset timestamp |
19
+
20
+ ## Budget Enforcement
21
+
22
+ | Key Pattern | Example | TTL | Worker | Purpose |
23
+ |---|---|---|---|---|
24
+ | `CONFIG:BUDGETS` | `CONFIG:BUDGETS` | None (synced) | sync-config | Budget JSON from budgets.yaml |
25
+ | `CONFIG:FEATURE:{key}:BUDGET_MONTHLY` | `CONFIG:FEATURE:my-app:scanner:BUDGET_MONTHLY` | None | sync-config | Monthly budget limit for feature |
26
+ | `BUDGET_WARN:{feature}:{metric}:{threshold}` | `BUDGET_WARN:my-app:scanner:d1_writes:70` | 1hr | platform-usage | Budget warning dedup (prevents duplicate Slack alerts) |
27
+ | `BUDGET_WARN_MONTHLY:{feature}:{limit}:exceeded` | `BUDGET_WARN_MONTHLY:my-app:scanner:d1_writes:exceeded` | 24hr | platform-usage | Monthly budget exceeded dedup |
28
+ | `BUDGET_WARN_MONTHLY:{feature}:{limit}:{threshold}` | `BUDGET_WARN_MONTHLY:my-app:scanner:d1_writes:70` | 24hr | platform-usage | Monthly warning threshold dedup |
29
+
30
+ ## Usage & Sampling State
31
+
32
+ | Key Pattern | Example | TTL | Worker | Purpose |
33
+ |---|---|---|---|---|
34
+ | `platform-usage:sampling-mode` | `platform-usage:sampling-mode` | None | platform-usage | Current sampling mode enum |
35
+ | `platform-usage:d1-writes-24h` | `platform-usage:d1-writes-24h` | None | platform-usage | Rolling 24h D1 write counter |
36
+ | `platform-usage:d1-writes-timestamp` | `platform-usage:d1-writes-timestamp` | None | platform-usage | Timestamp for write counter reset |
37
+ | `platform-usage:do-gb-seconds-24h:{project}` | `platform-usage:do-gb-seconds-24h:my-app` | None | platform-usage | DO GB-seconds per project |
38
+ | `platform-usage:pricing:v1` | `platform-usage:pricing:v1` | None | platform-usage | Cached pricing config |
39
+ | `platform-usage:prev-hour:account` | `platform-usage:prev-hour:account` | None | platform-usage | Delta calculation state |
40
+ | `platform-usage:prev-hour:timestamp` | `platform-usage:prev-hour:timestamp` | None | platform-usage | Last collection hour |
41
+
42
+ ## Settings Cache
43
+
44
+ | Key Pattern | Example | TTL | Worker | Purpose |
45
+ |---|---|---|---|---|
46
+ | `CONFIG:SETTINGS:ALL` | `CONFIG:SETTINGS:ALL` | 1hr | platform-usage | Full PlatformSettings JSON cache |
47
+ | `CONFIG:SETTINGS:{key}` | `CONFIG:SETTINGS:budget_soft_limit` | 1hr | platform-usage | Individual setting value cache |
48
+
49
+ ## Error Collection (Standard+ tier)
50
+
51
+ | Key Pattern | Example | TTL | Worker | Purpose |
52
+ |---|---|---|---|---|
53
+ | `SCRIPT_MAP:{scriptName}` | `SCRIPT_MAP:my-worker` | None | error-collector | Worker name to project mapping |
54
+ | `ERROR_FINGERPRINT:{hash}` | `ERROR_FINGERPRINT:a1b2c3` | None | error-collector | Cached known error state |
55
+ | `ISSUE_LOCK:{hash}` | `ISSUE_LOCK:a1b2c3` | 60s | error-collector | Race-condition dedup for GitHub issue creation |
56
+ | `TRANSIENT:{script}:{category}:{date}` | `TRANSIENT:my-worker:quota-exhausted:2026-03-02` | 24hr | error-collector | Transient error dedup window (1 issue/category/day) |
57
+ | `ERROR_RATE:{script}:{hour}` | `ERROR_RATE:my-worker:2026-03-02T14` | 2hr | error-collector | Hourly error rate counter |
58
+
59
+ ## Sentinel (Standard+ tier)
60
+
61
+ | Key Pattern | Example | TTL | Worker | Purpose |
62
+ |---|---|---|---|---|
63
+ | `sentinel:project-gaps:result` | `sentinel:project-gaps:result` | 1hr | platform-sentinel | Cached gap detection results |
64
+ | `alert-thresholds:config` | `alert-thresholds:config` | None | platform-sentinel | Alert threshold configuration |
65
+
66
+ ## Gap Alerts (Standard+ tier)
67
+
68
+ | Key Pattern | Example | TTL | Worker | Purpose |
69
+ |---|---|---|---|---|
70
+ | `GAP_ALERT:{project}:{date}` | `GAP_ALERT:my-app:2026-03-02` | 24hr | error-collector | Gap alert dedup (1 issue/project/day) |
71
+
72
+ ## Pattern Discovery (Full tier)
73
+
74
+ | Key Pattern | Example | TTL | Worker | Purpose |
75
+ |---|---|---|---|---|
76
+ | `PATTERNS:DYNAMIC:APPROVED` | `PATTERNS:DYNAMIC:APPROVED` | None (refreshed) | pattern-discovery | Approved patterns JSON cache for error-collector runtime |
77
+
78
+ ## Notifications (Full tier)
79
+
80
+ | Key Pattern | Example | TTL | Worker | Purpose |
81
+ |---|---|---|---|---|
82
+ | `NOTIFICATION_COUNT:{userId}` | `NOTIFICATION_COUNT:admin` | None | platform-notifications | Unread notification count |
83
+ | `NOTIFICATION_PREFS:{userId}` | `NOTIFICATION_PREFS:admin` | None | platform-notifications | User notification preferences |
84
+ | `NOTIFICATION_READ:{userId}:{notifId}` | `NOTIFICATION_READ:admin:abc123` | None | platform-notifications | Per-notification read state |
85
+
86
+ ## Alert Dedup
87
+
88
+ | Key Pattern | Example | TTL | Worker | Purpose |
89
+ |---|---|---|---|---|
90
+ | `ALERT:{key}:last_sent` | `ALERT:my-app:scanner:last_sent` | None | platform-usage | Alert send dedup |
91
+ | `SLACK_ALERT:{type}:{key}` | `SLACK_ALERT:budget:my-app:scanner` | 1hr | shared/slack-alerts | Slack message dedup |
92
+
93
+ ---
94
+
95
+ ## Key Conventions
96
+
97
+ - **Uppercase prefixes** (`CONFIG:`, `FEATURE:`, `BUDGET_WARN:`) = system state
98
+ - **Lowercase prefixes** (`platform-usage:`, `sentinel:`) = operational cache
99
+ - **TTL = None** means the key persists until explicitly deleted or overwritten
100
+ - **Dedup keys** use short TTLs (60s-24hr) to prevent duplicate actions
101
+ - All keys use `:` as separator (never `/` or `.`)
@@ -193,6 +193,7 @@ CREATE TABLE IF NOT EXISTS daily_usage_rollups (
193
193
 
194
194
  -- Vectorize metrics
195
195
  vectorize_queries INTEGER DEFAULT 0,
196
+ vectorize_inserts INTEGER DEFAULT 0,
196
197
  vectorize_vectors_stored_max INTEGER DEFAULT 0,
197
198
  vectorize_cost_usd REAL DEFAULT 0,
198
199
 
@@ -1,4 +1,4 @@
1
1
  -- Seed data: register your project in the platform
2
- INSERT INTO project_registry (project_id, display_name, status, tier, repository)
3
- VALUES ('{{projectSlug}}', '{{projectName}}', 'active', 'paid', '{{githubOrg}}/{{projectSlug}}')
2
+ INSERT INTO project_registry (project_id, display_name, status, repo_path)
3
+ VALUES ('{{projectSlug}}', '{{projectName}}', 'active', '{{githubOrg}}/{{projectSlug}}')
4
4
  ON CONFLICT (project_id) DO NOTHING;
@@ -36,10 +36,10 @@ const D1_DATABASE_NAME = 'YOUR_D1_DATABASE_NAME';
36
36
 
37
37
  interface FeatureDefinition {
38
38
  display_name: string;
39
- feature_id?: string;
40
39
  circuit_breaker: boolean;
41
40
  description?: string;
42
41
  cost_tier: string;
42
+ sources?: string[];
43
43
  }
44
44
 
45
45
  interface FeatureCategory {
@@ -49,36 +49,90 @@ interface FeatureCategory {
49
49
  interface Project {
50
50
  display_name: string;
51
51
  status: string;
52
- tier: string;
52
+ tier: number;
53
+ primary_resource?: string;
53
54
  repository?: string;
55
+ runbook?: string;
56
+ infrastructure?: unknown;
54
57
  features?: Record<string, FeatureCategory>;
55
58
  }
56
59
 
57
60
  interface Services {
58
- metadata: { version: string };
61
+ metadata: {
62
+ version: string;
63
+ lastUpdated: string;
64
+ };
59
65
  projects: Record<string, Project>;
60
66
  }
61
67
 
62
68
  interface BudgetLimit {
63
69
  d1_writes?: number;
64
70
  d1_reads?: number;
71
+ d1_rows_read?: number;
72
+ d1_rows_written?: number;
65
73
  kv_reads?: number;
66
74
  kv_writes?: number;
75
+ kv_deletes?: number;
76
+ kv_lists?: number;
77
+ r2_class_a?: number;
78
+ r2_class_b?: number;
79
+ ai_requests?: number;
80
+ ai_neurons?: number;
81
+ vectorize_queries?: number;
82
+ vectorize_inserts?: number;
67
83
  queue_messages?: number;
84
+ do_requests?: number;
85
+ workflow_invocations?: number;
68
86
  requests?: number;
69
87
  cpu_ms?: number;
70
88
  }
71
89
 
90
+ interface CircuitBreakerConfig {
91
+ enabled?: boolean;
92
+ auto_reset_seconds?: number;
93
+ cooldown_seconds?: number;
94
+ max_consecutive_trips?: number;
95
+ notes?: string;
96
+ }
97
+
98
+ interface FeatureOverride {
99
+ hourly?: BudgetLimit;
100
+ daily?: BudgetLimit;
101
+ monthly?: BudgetLimit;
102
+ circuit_breaker?: CircuitBreakerConfig;
103
+ }
104
+
105
+ interface GlobalLimits {
106
+ d1_write_limit?: number;
107
+ do_gb_seconds_daily_limit?: number;
108
+ }
109
+
72
110
  interface Budgets {
111
+ metadata: {
112
+ version: string;
113
+ lastUpdated: string;
114
+ };
73
115
  defaults: {
116
+ global_limits?: GlobalLimits;
74
117
  daily: BudgetLimit;
75
118
  circuit_breaker: {
76
119
  auto_reset_seconds: number;
77
120
  cooldown_seconds: number;
121
+ max_consecutive_trips: number;
122
+ };
123
+ error_budget?: {
124
+ error_rate_threshold: number;
125
+ window_minutes: number;
126
+ min_requests: number;
127
+ };
128
+ thresholds: {
129
+ warning: number;
130
+ critical: number;
78
131
  };
79
- thresholds: { warning: number; critical: number };
80
132
  };
81
- feature_overrides: Record<string, BudgetLimit>;
133
+ cost_tiers: Record<string, { multiplier: number; description: string }>;
134
+ project_budgets: Record<string, { allocation_percent: number; notes: string }>;
135
+ feature_overrides: Record<string, FeatureOverride>;
82
136
  }
83
137
 
84
138
  // =============================================================================
@@ -56,6 +56,9 @@ export interface PlatformSettings {
56
56
  // Resource limits (daily)
57
57
  d1WriteLimit: number;
58
58
  doGbSecondsDailyLimit: number;
59
+
60
+ // Gap detection
61
+ gapCoverageThresholdPct: number;
59
62
  }
60
63
 
61
64
  /**
@@ -104,6 +107,9 @@ export const DEFAULT_PLATFORM_SETTINGS: PlatformSettings = {
104
107
  // Resource limits (daily)
105
108
  d1WriteLimit: 1_000_000, // 1M writes per 24h (adaptive sampling trigger)
106
109
  doGbSecondsDailyLimit: 200_000, // 200K GB-seconds per 24h (~$2.50/day)
110
+
111
+ // Gap detection
112
+ gapCoverageThresholdPct: 90, // Per-project resource coverage threshold (percentage)
107
113
  };
108
114
 
109
115
  /**
@@ -128,6 +134,7 @@ export const SETTING_KEY_MAP: Record<string, keyof PlatformSettings> = {
128
134
  error_rate_min_requests: 'errorRateMinRequests',
129
135
  d1_write_limit: 'd1WriteLimit',
130
136
  do_gb_seconds_daily_limit: 'doGbSecondsDailyLimit',
137
+ gap_coverage_threshold_pct: 'gapCoverageThresholdPct',
131
138
  };
132
139
 
133
140
  /**
@@ -244,7 +251,13 @@ export async function getPlatformSettings(env: SettingsEnv): Promise<PlatformSet
244
251
  try {
245
252
  const parsed = JSON.parse(cached) as Partial<PlatformSettings>;
246
253
  // Merge with defaults to handle any missing keys
247
- return { ...DEFAULT_PLATFORM_SETTINGS, ...parsed };
254
+ const merged = { ...DEFAULT_PLATFORM_SETTINGS, ...parsed };
255
+ // Defense-in-depth: floor critical limits to prevent stale/poisoned cache values
256
+ if (merged.d1WriteLimit < 1000)
257
+ merged.d1WriteLimit = DEFAULT_PLATFORM_SETTINGS.d1WriteLimit;
258
+ if (merged.doGbSecondsDailyLimit < 1000)
259
+ merged.doGbSecondsDailyLimit = DEFAULT_PLATFORM_SETTINGS.doGbSecondsDailyLimit;
260
+ return merged;
248
261
  } catch {
249
262
  // Invalid JSON, fall through to D1
250
263
  }
@@ -404,4 +417,6 @@ export const EXPECTED_SETTINGS_KEYS = [
404
417
  // Resource limits
405
418
  'd1_write_limit',
406
419
  'do_gb_seconds_daily_limit',
420
+ // Gap detection
421
+ 'gap_coverage_threshold_pct',
407
422
  ];