@vegastack/skills 0.9.1 → 0.11.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/README.md +8 -3
- package/dist/index.js +5 -5
- package/package.json +1 -1
- package/skill/dev-architect/SKILL.md +96 -0
- package/skill/dev-architect/agents/openai.yaml +4 -0
- package/skill/dev-architect/references/ai-agents.md +89 -0
- package/skill/dev-architect/references/conventions.md +93 -0
- package/skill/{architect → dev-architect}/references/data.md +43 -44
- package/skill/dev-architect/references/infra.md +98 -0
- package/skill/dev-architect/references/mobile.md +75 -0
- package/skill/{architect → dev-architect}/references/pinned-facts.md +17 -16
- package/skill/dev-architect/references/principles.md +117 -0
- package/skill/{architect → dev-architect}/references/security.md +37 -44
- package/skill/dev-architect/references/stack.md +38 -0
- package/skill/dev-architect/references/web.md +102 -0
- package/skill/{architect → dev-architect}/refresh/REFRESH.md +8 -6
- package/skill/{architect → dev-architect}/refresh/sources.json +5 -10
- package/skill/dev-chronicle/SKILL.md +45 -0
- package/skill/dev-chronicle/agents/openai.yaml +4 -0
- package/skill/dev-chronicle/references/conventions.md +93 -0
- package/skill/dev-chronicle/refresh/REFRESH.md +3 -0
- package/skill/dev-chronicle/refresh/sources.json +6 -0
- package/skill/dev-debug/SKILL.md +43 -0
- package/skill/dev-debug/agents/openai.yaml +4 -0
- package/skill/dev-debug/references/conventions.md +93 -0
- package/skill/dev-debug/references/loop-ladder.md +20 -0
- package/skill/dev-debug/refresh/REFRESH.md +3 -0
- package/skill/dev-debug/refresh/sources.json +6 -0
- package/skill/dev-implement/SKILL.md +41 -36
- package/skill/dev-implement/references/conventions.md +93 -0
- package/skill/dev-implement/references/ledger-and-resume.md +27 -0
- package/skill/dev-implement/scripts/evidence-check.mjs +57 -0
- package/skill/dev-implement/scripts/lib/gh.mjs +93 -0
- package/skill/dev-implement/scripts/preflight.mjs +101 -0
- package/skill/dev-intake/SKILL.md +39 -33
- package/skill/dev-intake/references/brief-template.md +27 -12
- package/skill/dev-intake/references/conventions.md +93 -0
- package/skill/dev-intake/scripts/brief-lint.mjs +87 -0
- package/skill/dev-plan/SKILL.md +53 -0
- package/skill/dev-plan/agents/openai.yaml +4 -0
- package/skill/dev-plan/references/conventions.md +93 -0
- package/skill/dev-plan/references/plan-format.md +54 -0
- package/skill/dev-plan/refresh/REFRESH.md +3 -0
- package/skill/dev-plan/refresh/sources.json +6 -0
- package/skill/dev-plan/scripts/plan-lint.mjs +86 -0
- package/skill/dev-review/SKILL.md +69 -0
- package/skill/dev-review/agents/openai.yaml +4 -0
- package/skill/dev-review/assets/review-known-patterns.md.template +30 -0
- package/skill/dev-review/references/conventions.md +93 -0
- package/skill/dev-review/references/cross-agent.md +39 -0
- package/skill/dev-review/references/dispatch-prompts.md +104 -0
- package/skill/dev-review/references/security-axis.md +33 -0
- package/skill/dev-review/refresh/REFRESH.md +3 -0
- package/skill/dev-review/refresh/sources.json +6 -0
- package/skill/dev-setup/SKILL.md +14 -9
- package/skill/dev-setup/assets/agents-section.md.template +2 -2
- package/skill/dev-setup/assets/dev-profile.md.template +23 -5
- package/skill/dev-setup/references/conventions.md +93 -0
- package/skill/dev-setup/references/stack-playbooks.md +1 -1
- package/skill/dev-ship/SKILL.md +14 -7
- package/skill/dev-ship/references/conventions.md +93 -0
- package/skill/dev-ship/references/runbook.md +1 -1
- package/skill/dev-ship/scripts/ship-gate.mjs +213 -0
- package/skill/dev-status/SKILL.md +45 -0
- package/skill/dev-status/agents/openai.yaml +4 -0
- package/skill/dev-status/references/conventions.md +93 -0
- package/skill/dev-status/refresh/REFRESH.md +3 -0
- package/skill/dev-status/refresh/sources.json +6 -0
- package/skill/dev-status/scripts/status.mjs +152 -0
- package/skill/skill-maintainer/references/release-ops.md +3 -3
- package/skill/skillify/SKILL.md +1 -1
- package/skill/skillify/references/eval-playbook.md +6 -0
- package/skill-integrity.json +93 -33
- package/skill/architect/SKILL.md +0 -68
- package/skill/architect/agents/openai.yaml +0 -4
- package/skill/architect/assets/adr-template.md +0 -21
- package/skill/architect/assets/arch-template.md +0 -20
- package/skill/architect/references/advisory.md +0 -102
- package/skill/architect/references/ai-agents.md +0 -95
- package/skill/architect/references/infra.md +0 -128
- package/skill/architect/references/mobile.md +0 -78
- package/skill/architect/references/principles.md +0 -91
- package/skill/architect/references/project-profile.md +0 -37
- package/skill/architect/references/stack.md +0 -38
- package/skill/architect/references/web.md +0 -152
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Mobile — Flutter production doctrine
|
|
2
|
+
|
|
3
|
+
**The Flutter app is a separate repo from the web/API repo** — it consumes the Next.js
|
|
4
|
+
REST/OpenAPI contract as one more client, never a `mobile/` directory in the web monorepo
|
|
5
|
+
(register-recorded, corroborated three ways; an expensive structural call to get wrong).
|
|
6
|
+
|
|
7
|
+
Flutter is the production mobile framework when a product needs a mobile app (not all do —
|
|
8
|
+
dev.md's Architecture `mobile:` line records it). Baseline: Flutter 3.44.x stable;
|
|
9
|
+
Impeller is the default renderer on iOS and Android API 29+ (falls back below 29 — test
|
|
10
|
+
one API<29 device before shipping). Package versions here were verified 2026-08; re-verify
|
|
11
|
+
on pub.dev before pinning. Rules from the shipped VegaStack app are stated plainly; rules
|
|
12
|
+
from official-docs research MK has not ratified are tagged "(inferred)" — confirm on first
|
|
13
|
+
use, per SKILL.md.
|
|
14
|
+
|
|
15
|
+
## Architecture (official-guidance derived — inferred where the shipped app is silent)
|
|
16
|
+
|
|
17
|
+
- MVVM per official flutter.dev/app-architecture: View (widget, no logic) → ViewModel
|
|
18
|
+
(state + commands, 1:1 with its View) → Repository (source of truth, caching/retry,
|
|
19
|
+
never depends on another repository) → Service (thin stateless API/platform wrapper).
|
|
20
|
+
Skip the optional domain/use-case layer until logic is reused across ≥2 ViewModels.
|
|
21
|
+
- Layer-first structure: `lib/{data, domain, ui, routing, config}`, feature folders inside
|
|
22
|
+
`ui/`, shared widgets in `ui/core/`. (Blog "feature-first is the standard" claims don't
|
|
23
|
+
survive verification — the official reference app is layer-first; feature-first is a
|
|
24
|
+
valid escalation at scale.) Class names mirror roles: `HomeViewModel`, `UserRepository`.
|
|
25
|
+
|
|
26
|
+
## State management — lean by default
|
|
27
|
+
|
|
28
|
+
- Plain `ChangeNotifier`/`ValueNotifier` ViewModels with hand-wired constructor injection
|
|
29
|
+
in `main.dart` — zero extra dependencies, zero codegen; matches official guidance and
|
|
30
|
+
what VegaStack has shipped.
|
|
31
|
+
- Escalate to Riverpod only when async state genuinely needs sharing across ≥3 widgets,
|
|
32
|
+
tests need provider-override mocking, or a second app shares a state-heavy module. No
|
|
33
|
+
get_it — official docs steer away from service locators; `provider` is the official DI
|
|
34
|
+
pick if constructor wiring gets unwieldy.
|
|
35
|
+
|
|
36
|
+
## Networking & auth
|
|
37
|
+
|
|
38
|
+
- One `dio` client centralized in a single `ApiClient` — never scattered HTTP calls; the
|
|
39
|
+
app consumes the same contract-first REST API as the web app (web.md). That versioned
|
|
40
|
+
`/api/v1` contract outlives web deploy cycles: app-store install lag keeps old clients
|
|
41
|
+
alive, so a shipped mobile app counts as real users even while the web side iterates
|
|
42
|
+
freely — the one exception to pre-launch delete-not-migrate and to dead-endpoint
|
|
43
|
+
deletion.
|
|
44
|
+
- Auth is the same Better Auth instance as web, via the bearer plugin: capture the token
|
|
45
|
+
from the `set-auth-token` response header on sign-in; store in `flutter_secure_storage`
|
|
46
|
+
(never shared_preferences); attach `Authorization: Bearer` via a dio interceptor; clear
|
|
47
|
+
storage and route to sign-in on 401.
|
|
48
|
+
- Do NOT depend on `better_auth_flutter` (0.1.0, negligible adoption as of 2026-08) —
|
|
49
|
+
hand-roll the interceptor; revisit at a real 1.0. `shared_preferences` for non-secret
|
|
50
|
+
local metadata only; `drift` only for genuine offline/relational needs — never
|
|
51
|
+
speculatively.
|
|
52
|
+
|
|
53
|
+
## Design system on mobile
|
|
54
|
+
|
|
55
|
+
Semantic colors via a hand-authored `ColorScheme` plus `ThemeExtension` for tokens outside
|
|
56
|
+
Material's roles — mirroring the web design-system token names 1:1 from one Dart source of
|
|
57
|
+
truth. House taste mapped: `CardTheme(elevation: 0)` with `outlineVariant` borders (flat,
|
|
58
|
+
borders-only); TextTheme capped at `FontWeight.w600`, never bold; subtle motion with
|
|
59
|
+
reduced-motion respected; Lucide-style iconography.
|
|
60
|
+
|
|
61
|
+
## Navigation, models, testing, deploy
|
|
62
|
+
|
|
63
|
+
- Navigation: the shipped app uses plain `Navigator`; adopt `go_router` when deep
|
|
64
|
+
links/route state demand it, not by reflex (inferred).
|
|
65
|
+
- Models: hand-written by default (what the shipped app does); freezed +
|
|
66
|
+
json_serializable only when codegen demonstrably earns its build cost (inferred).
|
|
67
|
+
- Test where MVVM pays off: unit-test ViewModels and Repositories; widget-test critical
|
|
68
|
+
screens; integration tests only for can't-ship-broken flows (sign-in, payment). Golden
|
|
69
|
+
tests, if adopted: `alchemist` over the discontinued `golden_toolkit` (inferred).
|
|
70
|
+
- Deploy: GitHub Actions is the house CI; Fastlane for store signing/upload and real build
|
|
71
|
+
flavors (`--flavor` + per-env entry points) are the researched defaults (inferred — no
|
|
72
|
+
shipped store-deploy precedent; confirm before wiring).
|
|
73
|
+
|
|
74
|
+
Undecided (ask MK rather than assume): push-notification provider, offline/sync
|
|
75
|
+
expectations per product, store-release cadence.
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# Pinned platform facts
|
|
2
2
|
|
|
3
3
|
Dated, source-verified facts that change architecture decisions and that models routinely
|
|
4
|
-
get wrong from stale training data. This is the
|
|
4
|
+
get wrong from stale training data. This file is the verified cache behind SKILL.md's
|
|
5
|
+
verify-before-you-recommend protocol, and the ONLY file in this skill that goes stale by
|
|
5
6
|
itself — the weekly refresh (see refresh/REFRESH.md) re-verifies it. When a recommendation
|
|
6
7
|
leans on a fact older than 60 days, re-verify that one fact against its source first.
|
|
7
8
|
|
|
@@ -38,7 +39,12 @@ All facts below verified 2026-08-12.
|
|
|
38
39
|
- **PPR flags are gone** — `experimental.ppr` no longer exists; partial prerendering is
|
|
39
40
|
part of `cacheComponents: true` (which also replaced `dynamicIO`). [nextjs.org/blog]
|
|
40
41
|
- **`middleware.ts` is replaced by `proxy.ts` running on Node** — full fs/crypto/native
|
|
41
|
-
package access in request interception.
|
|
42
|
+
package access in request interception.
|
|
43
|
+
- **`proxy.ts`/Node middleware does NOT work on OpenNext Cloudflare as of 2026-08** (open
|
|
44
|
+
issues opennextjs-cloudflare#962/#1277, workers-sdk#13755/#13937) — don't design a
|
|
45
|
+
Cloudflare-hosted feature around `proxy.ts`; re-check the trackers before assuming it
|
|
46
|
+
shipped. Turbopack is supported since adapter v1.15.0 (the old breakage is fixed;
|
|
47
|
+
re-verify only on older pins).
|
|
42
48
|
- **The Adapter API is stable since 16.2** — Vercel's adapter and Cloudflare's OpenNext
|
|
43
49
|
adapter share the same public contract, but Cloudflare's still trails on newest features;
|
|
44
50
|
check the deployment feature matrix per feature, don't assume parity.
|
|
@@ -57,15 +63,14 @@ All facts below verified 2026-08-12.
|
|
|
57
63
|
- **1.7.0 is in RC** (rc.5 shipped 2026-08-11, same day as the pinned patch). Stay on
|
|
58
64
|
1.6.x until 1.7 is stable; queued breaking changes include the MCP plugin restructure
|
|
59
65
|
(moves to `@better-auth/mcp`) and SAML IdP-initiated default-off. [github.com/better-auth]
|
|
60
|
-
|
|
61
66
|
- **The organizations plugin models teams, invitations, and custom RBAC end-to-end**
|
|
62
|
-
(`teams: { enabled: true }`, `invite-member` with `teamId`, `createAccessControl`)
|
|
63
|
-
|
|
67
|
+
(`teams: { enabled: true }`, `invite-member` with `teamId`, `createAccessControl`).
|
|
68
|
+
[better-auth.com/docs]
|
|
64
69
|
- **Better Auth ships an apiKey plugin** (docs/plugins/api-key — verified live
|
|
65
70
|
2026-08-12; an older internal note claiming otherwise was wrong). Default to the plugin
|
|
66
|
-
for new projects; the flagship platform's native implementation
|
|
67
|
-
|
|
68
|
-
|
|
71
|
+
for new projects; the flagship platform's native implementation is a recorded project
|
|
72
|
+
decision, not the house default. The `bearer` plugin covers token session transport
|
|
73
|
+
(the mobile/Flutter mechanism).
|
|
69
74
|
- **`twoFactor` supports `allowPasswordless: true`** for users without password accounts
|
|
70
75
|
(passkey/OAuth/magic-link signups).
|
|
71
76
|
|
|
@@ -73,16 +78,12 @@ All facts below verified 2026-08-12.
|
|
|
73
78
|
|
|
74
79
|
- **EVE (`eve` on npm, github.com/vercel/eve) is Vercel's durable-agent framework —
|
|
75
80
|
v0.33.2, still beta/pre-GA, shipping near-daily.** Filesystem-first agents; every
|
|
76
|
-
session a durable, resumable workflow.
|
|
77
|
-
as Vercel Functions with Fluid Compute (a recorded per-project exception to the hosting
|
|
78
|
-
default), or self-hosted as a long-running Node/OCI service beside Postgres. Never a
|
|
79
|
-
request-scoped/edge function (a Cloudflare Worker included) in either shape.
|
|
80
|
-
[vercel.com/docs/eve]
|
|
81
|
+
session a durable, resumable workflow. [vercel.com/docs/eve]
|
|
81
82
|
- **Self-hosted EVE durability (`@workflow/world-postgres`, stable 4.3.x) explicitly
|
|
82
83
|
requires a long-lived worker process — "not compatible with serverless platforms".**
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
84
|
+
The 5.0.0-beta channel exists; don't pin it without a documented reason. Internally it
|
|
85
|
+
uses graphile-worker — it is not pg-boss and doesn't replace it.
|
|
86
|
+
[workflow-sdk.dev/worlds/postgres]
|
|
86
87
|
- **pg-boss is at 12.x** — Postgres-native (`SKIP LOCKED`), no Redis. The right default
|
|
87
88
|
for simple background jobs/cron on this stack; BullMQ only when a genuinely complex job
|
|
88
89
|
graph (flows, dependencies, rate-limited pipelines) demands Redis. [npm: pg-boss]
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# Principles — how VegaStack decides, reviews, and talks
|
|
2
|
+
|
|
3
|
+
Distilled from seven months of MK's sessions and repos. Each rule carries its why — apply
|
|
4
|
+
the reasoning, not just the rule.
|
|
5
|
+
|
|
6
|
+
## Build lean first
|
|
7
|
+
|
|
8
|
+
One deployable until a concrete requirement forces a split. A single, properly structured
|
|
9
|
+
Next.js app owns the UI, RSC, route handlers, auth, and the REST/OpenAPI control plane — no
|
|
10
|
+
NestJS or Hono beside it, no speculative queue, cache, or worker; a notification sender is
|
|
11
|
+
a cron handler inside the app, not its own deployable. **Why:** agents habitually propose
|
|
12
|
+
services MK then strips out; on a 3-4 person team every moving part is real maintenance,
|
|
13
|
+
and the lean version is usually also the faster, more reliable one. Lean-first governs the
|
|
14
|
+
*count of moving parts*, not the rigor inside each — money, auth, tenancy, audit, and
|
|
15
|
+
secrets always get full rigor.
|
|
16
|
+
|
|
17
|
+
## Every moving part names its trigger
|
|
18
|
+
|
|
19
|
+
Propose infrastructure only together with the trigger that justifies it, stated in the
|
|
20
|
+
recommendation: "a separate worker WHEN jobs exceed request timeouts", "a queue WHEN volume
|
|
21
|
+
makes inline processing lossy". Provision only what the current build phase actually uses —
|
|
22
|
+
infrastructure tracks real usage, never anticipated usage. **Why:** MK stated "OpenBao
|
|
23
|
+
mandatory in production" and walked it back five days later. Blanket mandates rot; triggers
|
|
24
|
+
stay true as projects differ.
|
|
25
|
+
|
|
26
|
+
## Pre-launch means delete, not migrate
|
|
27
|
+
|
|
28
|
+
Zero real users = no backward compatibility, no legacy shims, no deprecation windows, no
|
|
29
|
+
feature flags hiding unfinished work. Delete outright; reset the dev database rather than
|
|
30
|
+
writing migration chains. This is the DEFAULT — most VegaStack projects are pre-launch at
|
|
31
|
+
any given time; expand/migrate/contract discipline begins when real users exist. **Why:**
|
|
32
|
+
carrying compatibility for users who don't exist is pure bloat. One exception: a versioned
|
|
33
|
+
API contract consumed by a shipped mobile app counts as real users even while the web side
|
|
34
|
+
iterates freely — app-store install lag keeps old clients alive (mobile.md).
|
|
35
|
+
|
|
36
|
+
## Reuse before you build new
|
|
37
|
+
|
|
38
|
+
Extend the existing table, service, or spine (ACL, change-log, outbox, realtime channel)
|
|
39
|
+
before creating a parallel one; when two components do the same job, merge them. Promote a
|
|
40
|
+
util to `/lib` the moment a second feature uses it. **Why:** two sources of the same truth
|
|
41
|
+
always drift — the reference-architecture mistake MK explicitly engineers against.
|
|
42
|
+
|
|
43
|
+
## Enforce boundaries mechanically
|
|
44
|
+
|
|
45
|
+
Architectural boundaries that matter get a CI guard script that fails the build — monorepo
|
|
46
|
+
import direction (apps → packages, never the reverse; workers never import UI/React),
|
|
47
|
+
runtime gravity, server/client separation. **Why:** convention alone was tried and failed;
|
|
48
|
+
a guard script is cheaper than re-reviewing the same violation forever.
|
|
49
|
+
|
|
50
|
+
## Runtime gravity: long-running work never lives in the request tier
|
|
51
|
+
|
|
52
|
+
Anything that can run long, hold a connection, or outlive a request — agent execution, job
|
|
53
|
+
processing, media pipelines — runs in a separate worker/runner tier, never inside a route
|
|
54
|
+
handler or an OpenNext Worker. **Why:** request-scoped tiers have timeouts and body limits;
|
|
55
|
+
executing workflows inside Next.js handlers is the anti-pattern MK cites most.
|
|
56
|
+
|
|
57
|
+
## Effort scales with stakes, not habit
|
|
58
|
+
|
|
59
|
+
Security, auth, tenancy, money, and foundations get generous, adversarial treatment.
|
|
60
|
+
Routine features on a small team get medium thoroughness — a cheap reconnaissance pass
|
|
61
|
+
before full-cost work, and no governance ceremony a 3-4 person team won't exercise.
|
|
62
|
+
**Why:** MK's own latest self-correction — his previous architecture skill "got too
|
|
63
|
+
complicated" by applying flagship-platform rigor everywhere.
|
|
64
|
+
|
|
65
|
+
## Decisions are verified, recorded, and reversible for a reason
|
|
66
|
+
|
|
67
|
+
- Resolve uncertainty with evidence, never the safer-sounding guess (SKILL.md's verify
|
|
68
|
+
protocol). MK refused an unverified "Better Auth forces text UUID columns" claim — false.
|
|
69
|
+
- Present decisions as 2-3 options with a clear recommendation and the tradeoff that
|
|
70
|
+
matters; record the choice as one dated register line — the reader learns the reasoning.
|
|
71
|
+
- MK reverses when: a verified assumption proves false · cleverness regresses UX · a
|
|
72
|
+
heavyweight mandate meets a simple project · his own tooling over-complicates. He
|
|
73
|
+
reverses toward less machinery on low stakes, toward more rigor only on a concrete bug
|
|
74
|
+
or vulnerability. Anticipate this: don't defend machinery he'd delete.
|
|
75
|
+
|
|
76
|
+
## Context gates rigor — ask, don't assume
|
|
77
|
+
|
|
78
|
+
Rigor flexes on facts, not labels: pre-launch or live · internal, client, or OSS ·
|
|
79
|
+
self-hosted or managed · money/PII or not. These live in dev.md's `## Architecture`
|
|
80
|
+
section. When two recorded decisions conflict or the facts can't answer, ask MK with a
|
|
81
|
+
recommendation instead of assuming.
|
|
82
|
+
|
|
83
|
+
## Review discipline (design reviews, audits)
|
|
84
|
+
|
|
85
|
+
- Adversarial by default: assume the work is wrong until disproven — findings or verified
|
|
86
|
+
absence of findings, never praise. Evidence or it doesn't exist: every finding cites
|
|
87
|
+
file:line actually read, quoted verbatim; detection is never a claim of absence.
|
|
88
|
+
- Verify every candidate finding before reporting: verdict true-positive / false-positive
|
|
89
|
+
/ duplicate / lower-severity, with disproving evidence for the false positives.
|
|
90
|
+
- Severity, three tiers with required actions: **critical** — exploitable or data-losing;
|
|
91
|
+
blocks ship, MK signs off on the fix. **production-gate** — fixed before the surface
|
|
92
|
+
serves real users; fine behind pre-launch. **consider** — advisory; log and move on.
|
|
93
|
+
Never round up; judge severity against the project's Architecture facts — never surface
|
|
94
|
+
platform-scale concerns as defects on a simple project.
|
|
95
|
+
- Cheap deterministic checks belong in every review: dead exports, unpaginated lists,
|
|
96
|
+
`SELECT *` at API boundaries, missing tenant/FK indexes, fresh-clone buildability.
|
|
97
|
+
- Coverage without bias: evaluate the review's scope, not just what changed or what you
|
|
98
|
+
built. End honestly: open questions, not-verified items, accepted risks named as such.
|
|
99
|
+
|
|
100
|
+
## Advise, never gate
|
|
101
|
+
|
|
102
|
+
You recommend; MK and the team decide. A departure from a recommendation becomes one dated
|
|
103
|
+
accepted-risk line proposed for the register, reported honestly in later reviews — never
|
|
104
|
+
silenced, never blocked on, never re-litigated.
|
|
105
|
+
|
|
106
|
+
## Voice — a team briefing, not a compliance report
|
|
107
|
+
|
|
108
|
+
Plain language, short sentences, terms defined on first use. Recommendation first, then
|
|
109
|
+
the one risk that matters, then detail in bullets and tables. Plain markdown, no JSON
|
|
110
|
+
blocks. No em dashes, emojis, or hashtags in copy MK will publish.
|
|
111
|
+
|
|
112
|
+
## Client engagements (`kind: client`)
|
|
113
|
+
|
|
114
|
+
Same stack defaults, gates, and honesty — a client never gets a looser standard. Scope
|
|
115
|
+
inversion is named the moment it's seen (SOW drift surfaces with options, never silently
|
|
116
|
+
absorbed); client-driven stack overrides are dated register lines with MK's sign-off; the
|
|
117
|
+
register plus the issue briefs are the handover record.
|
|
@@ -6,22 +6,22 @@ every change, and a focused security audit after any auth-adjacent change before
|
|
|
6
6
|
## Authentication (Better Auth, always)
|
|
7
7
|
|
|
8
8
|
- Email/password + Google sign-in is the default configuration; magic link and email OTP
|
|
9
|
-
as flows demand; 2FA TOTP when the product warrants (
|
|
10
|
-
passkey/OAuth-only users). Follow Better Auth's documented APIs — never hand-roll
|
|
11
|
-
or cache invalidation beside them.
|
|
12
|
-
- The organizations plugin (
|
|
13
|
-
organization maps to workspace; "user groups" of any
|
|
14
|
-
|
|
9
|
+
as flows demand; 2FA TOTP when the product warrants (`allowPasswordless: true` for
|
|
10
|
+
passkey/OAuth-only users). Follow Better Auth's documented APIs — never hand-roll
|
|
11
|
+
session or cache invalidation beside them.
|
|
12
|
+
- The organizations plugin (teams enabled) owns orgs/workspaces/teams/invitations —
|
|
13
|
+
organization maps to workspace (`modelName: "workspace"` pattern); "user groups" of any
|
|
14
|
+
kind are Better Auth teams; never a hand-rolled workspace/membership/groups schema. The
|
|
15
|
+
SSO plugin covers SAML/OIDC when enterprise auth arrives — don't build protocol code.
|
|
15
16
|
- Mobile uses the bearer plugin (token from `set-auth-token`, stored in secure storage) —
|
|
16
17
|
same auth instance, same Postgres, as the web app.
|
|
17
|
-
- Sessions: rolling expiry, Postgres-authoritative.
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
server-side — never a hand-rolled cache-invalidation scheme beside them.
|
|
18
|
+
- Sessions: rolling expiry, Postgres-authoritative. Don't enable cookie-cache-style
|
|
19
|
+
shortcuts without checking Better Auth's current issues — a cookieCache bug once caused
|
|
20
|
+
silent 5-minute logouts in production. Revocation ("sign out everywhere",
|
|
21
|
+
admin-initiated) goes through Better Auth's session-list/revoke APIs server-side.
|
|
22
22
|
- Google OAuth footgun: set `baseURL` explicitly in production config — an unset or wrong
|
|
23
23
|
value silently targets localhost and fails Google's exact-match redirect-URI check.
|
|
24
|
-
- API keys:
|
|
24
|
+
- API keys: Better Auth's apiKey plugin by default. Whatever implements them, the
|
|
25
25
|
invariants hold: hash-stored with a recognizable prefix, raw value shown exactly once
|
|
26
26
|
and never cached or logged again, constant-time compare on verify.
|
|
27
27
|
|
|
@@ -31,25 +31,27 @@ every change, and a focused security audit after any auth-adjacent change before
|
|
|
31
31
|
server-only data-access layer — `requireSession()`/`requireOrgRole()`-style helpers,
|
|
32
32
|
re-checked per resource, on every route, auth before body parse.
|
|
33
33
|
- Every check fails closed: a policy-engine error, throw, or unmatched rule resolves to
|
|
34
|
-
deny, and the deny is still audited. No `DISABLE_AUTH
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
deny, and the deny is still audited. No `DISABLE_AUTH`-style escape hatches, ever;
|
|
35
|
+
dev-only conveniences only when explicitly gated to non-production with zero prod
|
|
36
|
+
behavior change.
|
|
37
37
|
- Role models stay small — Owner/Admin/Member covers most products. A policy engine
|
|
38
|
-
(Cedar-class ABAC) needs a named trigger — fine-grained multi-principal authorization
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
(Cedar-class ABAC) needs a named trigger — fine-grained multi-principal authorization at
|
|
39
|
+
platform scale; today only the flagship platform has earned it. Anyone else proposing
|
|
40
|
+
one: present the trigger and ask MK.
|
|
41
41
|
- Tenant identity always derives from the authenticated principal — never from a
|
|
42
42
|
client-supplied workspace/org ID (a trusted `?workspaceId=` param caused a real
|
|
43
|
-
cross-tenant IDOR). Cross-tenant lookups return 404, never 403 — no
|
|
43
|
+
cross-tenant IDOR; reject on mismatch). Cross-tenant lookups return 404, never 403 — no
|
|
44
|
+
existence oracle.
|
|
44
45
|
- If ALL UI consumers of a route sit inside the authenticated app shell, the route
|
|
45
46
|
requires auth even when its data "seems public" — trace actual callers before accepting
|
|
46
|
-
"intentionally public".
|
|
47
|
-
|
|
47
|
+
"intentionally public". Guest/anonymous write paths get the same rigor as authenticated
|
|
48
|
+
ones — never looser.
|
|
49
|
+
- Tenancy at the data layer: RLS ENABLE+FORCE plus explicit scoping — data.md.
|
|
48
50
|
|
|
49
51
|
## Secrets
|
|
50
52
|
|
|
51
|
-
- No plaintext secrets anywhere: not in code, config
|
|
52
|
-
|
|
53
|
+
- No plaintext secrets anywhere: not in code, config, wrangler.jsonc, generated output,
|
|
54
|
+
logs, audit records (redact to a short prefix), agent state, or JSONB columns.
|
|
53
55
|
Cloudflare Worker secrets and GitHub secrets are the storage; a credential broker
|
|
54
56
|
(envelope AES-256-GCM, AAD bound to org+credential+key-version, fresh per-secret DEK)
|
|
55
57
|
when the product stores third-party credentials.
|
|
@@ -60,29 +62,22 @@ every change, and a focused security audit after any auth-adjacent change before
|
|
|
60
62
|
- MK enters OTP/2FA/credentials himself, always. Agents never type or automate through
|
|
61
63
|
credential prompts.
|
|
62
64
|
|
|
63
|
-
## Requests
|
|
65
|
+
## Requests out and untrusted content
|
|
64
66
|
|
|
65
|
-
- Validate every input against its contract before use — no blind casts of params, query,
|
|
66
|
-
body, or headers. Stream body-size limits with early abort.
|
|
67
|
-
- CSRF on every cookie-authenticated mutation (bearer-token flows exempt — no cookies).
|
|
68
|
-
Rate-limit unauthenticated and sensitive write endpoints through one shared
|
|
69
|
-
(Postgres-native) mechanism. Guest/anonymous write paths get the same authorization
|
|
70
|
-
rigor as authenticated ones — never looser.
|
|
71
67
|
- All outbound HTTP through one SSRF-hardened egress client: DNS-resolve then deny
|
|
72
68
|
private/loopback/link-local/CGNAT/ULA ranges, pin the socket to the resolved IP, exact
|
|
73
|
-
host allowlist (no suffix matching),
|
|
74
|
-
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
(see ai-agents.md).
|
|
69
|
+
host allowlist (no suffix matching), re-validate every redirect hop.
|
|
70
|
+
- Body-size limits stream: count bytes as they arrive and abort at the limit — never
|
|
71
|
+
buffer the whole body first.
|
|
72
|
+
- Third-party/webhook/agent content is untrusted input — sanitize before rendering or
|
|
73
|
+
acting on it. The instruction/data separation agent products must keep: ai-agents.md.
|
|
79
74
|
|
|
80
75
|
## Data protection
|
|
81
76
|
|
|
82
|
-
- Erasure by crypto-shredding: per-subject keys; erase = destroy the key.
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
77
|
+
- Erasure by crypto-shredding: per-subject keys; erase = destroy the key. Implemented
|
|
78
|
+
only when sealing is wired into every PII write path — a defined-but-unused utility is
|
|
79
|
+
a finding, not a feature. Legal hold blocks GC; retention classes derived, not
|
|
80
|
+
hardcoded.
|
|
86
81
|
- Object keys never leak raw user/workspace IDs (data.md). Never log PII beyond user IDs.
|
|
87
82
|
- Audit log: tamper-evident (hash-chained where the product warrants), separate from sync
|
|
88
83
|
and versioning tables, pending-then-settle around side effects. Hash-chain writes lock
|
|
@@ -91,7 +86,5 @@ every change, and a focused security audit after any auth-adjacent change before
|
|
|
91
86
|
|
|
92
87
|
## Verifying security findings
|
|
93
88
|
|
|
94
|
-
Scanner
|
|
95
|
-
|
|
96
|
-
blast radius, and the smallest safe fix — then a regression test. Don't round severity up,
|
|
97
|
-
and don't patch what you haven't confirmed.
|
|
89
|
+
Scanner/reviewer output follows the review discipline in principles.md — verdict per
|
|
90
|
+
finding, no rounding up. Additionally: every confirmed finding gets a regression test.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Stack — locked decisions
|
|
2
|
+
|
|
3
|
+
The VegaStack default stack. "Not" columns are real rejections MK has made — do not
|
|
4
|
+
re-propose them without new facts. Current versions and platform caveats live in
|
|
5
|
+
[pinned-facts](pinned-facts.md); check there before pinning a version.
|
|
6
|
+
|
|
7
|
+
| Area | Use | Not | Why |
|
|
8
|
+
|---|---|---|---|
|
|
9
|
+
| Web framework | Next.js App Router, one app | NestJS, Hono, a second backend | A properly structured Next app owns web + API + auth for web, Flutter, MCP, and public consumers; a second framework is pure maintenance surface |
|
|
10
|
+
| Runtime / package manager | Bun (default for new projects); pnpm fully sanctioned where chosen | npm, yarn — never | One lockfile discipline per project; dev.md records which. Commit text lockfiles (`bun.lock`, not `bun.lockb`) |
|
|
11
|
+
| Auth | Better Auth, always — default flows, plugins, and the org→workspace mapping: security.md | Hand-rolled auth, custom user-groups schema, Auth0/Clerk | Owner-stated standing rule; prefer the shipped plugins over native builds unless a project records why |
|
|
12
|
+
| Database | PostgreSQL, always self-managed by us: PlanetScale Postgres server or self-hosted (Hetzner or similar), behind Hyperdrive on Workers. D1-only is a recorded exception for the minimal Cloudflare-native product class (locked 2026-05-20) — check dev.md's `## Architecture` before assuming Postgres | Neon (never), D1 as a secondary store beside Postgres, MySQL | "We don't use neon at all." One datastore per product. D1's sanctioned sidecar case: a Worker-scoped idempotency table for Stripe webhooks — Postgres still owns the ledger |
|
|
13
|
+
| ORM | Drizzle + drizzle-kit, single `postgres-js` driver | Prisma | House standard across every repo since Feb 2026 |
|
|
14
|
+
| DB from Workers | Hyperdrive binding, per-request client — discipline in data.md | Global pools, TCP clients (ioredis) in Workers | workerd forbids I/O across requests; a module-level pool is a bug, not a style choice |
|
|
15
|
+
| Storage | Cloudflare R2 (S3-compatible API), presigned URLs, short-lived scoped access | S3 + CloudFront by reflex | R2 egress is $0 at any scale — the cost problem S3+CDN solves doesn't exist here. Keep the S3 protocol boundary so any S3 provider or MinIO works for licensed self-hosted deployments |
|
|
16
|
+
| Cache / Redis | None by default. Rate limiting and caching Postgres-native; Workers KV only with a named trigger (e.g. read-mostly config cache at volumes where a Postgres round-trip measurably hurts — the recorded auth-cache migration); a Redis-class store never correctness-bearing | Upstash Redis (migrated off), Redis "because caching" | "No Redis in P1" — a cache layer is a moving part; Postgres already exists. Never cache authorization/role data aggressively (data.md) |
|
|
17
|
+
| Jobs / cron | pg-boss on the existing Postgres, dispatcher-only — lease/heartbeat/retry state of authority in our own tables. Cron parsing/description: `croner` (DST/IANA-aware) + `cronstrue` | BullMQ+Redis, Temporal, CF Queues by default; `node-cron`, `cron-parser` | Jobs are simple; Postgres is already there. Owning durability state keeps the queue library swappable; a cron-parser swap was made and corrected once already |
|
|
18
|
+
| Agent execution | EVE (Vercel's `eve`) — deploy shapes and constraints: ai-agents.md | EVE inside an OpenNext Worker or any request-scoped/edge function | EVE's Postgres world requires a long-lived worker process; EVE owns agent sessions, pg-boss owns generic jobs — never conflated |
|
|
19
|
+
| AI calls | AI SDK behind a thin adapter; Anthropic default provider; Cloudflare AI Gateway for routing/telemetry when on Cloudflare | Hardcoded model IDs scattered in code, per-provider SDKs everywhere | Adapter keeps providers swappable; the gateway centralizes cost/telemetry without building it |
|
|
20
|
+
| Design system | Consume `@vegastack/design` + `@vegastack/ui` (Base UI primitives, semantic tokens) | Creating/modifying components upstream, raw shadcn edits, Radix for new work | Consume, don't extend — upstream changes are MK's deliberate decision. Base UI locked over Radix 2026-07 |
|
|
21
|
+
| Frontend state | Server state via RSC + TanStack Query; URL state via nuqs; ephemeral UI state via Zustand | Persisting remote/tenant data client-side (IndexedDB/local-first) for multi-tenant SaaS | Governance: tenant data never rests on the client. Local-first only for a confirmed single-tenant/offline product — ask first |
|
|
22
|
+
| Realtime | SSE tailing an event log first; Durable Objects (SQLite, WebSocket hibernation) when on Cloudflare and bidirectional state is real. One DO per collaboration scope (a `WorkspaceHub` for presence, a per-document `PageSync` for edits) — never one monolithic DO | socket.io + Redis pub/sub, Ably, Pusher | SSE covers most "live" needs with zero new services; hibernating DOs bill ~nothing while idle. Third-party realtime vendors were migrated off |
|
|
23
|
+
| Collaborative editing | Tiptap editor (markdown as source of truth), Yjs CRDT sync via `y-partyserver` inside the document DO; server-side sanitization/versioning applies to every CRDT write | CodeMirror (abandoned 2026-05-21), ElectricSQL (removed), RxDB (reversed to plain Dexie where local cache is needed) | Locked through real reversals; CRDT must never become an XSS/version/audit bypass |
|
|
24
|
+
| Analytics | Self-hosted Plausible (`pb.vegastack.com`), proxied via `next-plausible` where applicable | Google Analytics, Vercel Analytics, PostHog by default | Self-hosted, privacy-clean, already running — recurs across 5 projects |
|
|
25
|
+
| Hosting | Cloudflare Workers via OpenNext, or self-managed servers (Docker; Coolify for push-to-deploy) — recorded in dev.md's Architecture | Vercel as a default (per-project recorded exception only); a parallel Vercel path once committed to Cloudflare | Cost and egress economics favor Cloudflare/self-host; split deploy paths drift. EVE-hosted workloads are a legitimate Vercel exception |
|
|
26
|
+
| Email | AWS SES (behind an adapter); bounces/complaints via the SNS-webhook pattern into a suppression list | Per-vendor SDK sprawl, sending to suppressed addresses | Cheap, boring, proven in-house; unhandled bounces poison sender reputation |
|
|
27
|
+
| Payments | Stripe — money-path mechanics: web.md | Building billing logic inside request handlers | Money paths get the full rigor tier |
|
|
28
|
+
| Monorepo | Turborepo + workspaces (Bun or pnpm) when there is more than one package; apps → packages only, enforced by a boundary check | Deep relative cross-package imports, packages importing apps | Import direction is a guard script, not a convention |
|
|
29
|
+
| i18n | next-intl, `localePrefix: 'as-needed'`; no hardcoded user-facing strings | Ad-hoc string tables | Already the proven pattern; English-only today but scaffolded |
|
|
30
|
+
| APIs | Contract-first: zod schemas → OpenAPI 3.1 — detail: web.md | Route-local validation, raw `request.json()`, unbounded lists | One contract feeds web, Flutter, MCP, and public consumers |
|
|
31
|
+
|
|
32
|
+
## Choosing between the two hosting targets
|
|
33
|
+
|
|
34
|
+
Cloudflare (OpenNext) when: public web product, global latency matters, R2/DO/Queues fit,
|
|
35
|
+
cost-per-request dominates. Self-managed (Docker/Hetzner) when: self-hosting is a product
|
|
36
|
+
requirement (licensed/enterprise), the workload needs long-lived processes (EVE, heavy
|
|
37
|
+
workers), or platform independence is worth ~30 min/month of ops. Many products use both:
|
|
38
|
+
OpenNext app on Cloudflare + a long-running worker container beside the database.
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# Web — frontend, backend/API taste
|
|
2
|
+
|
|
3
|
+
## Project layout
|
|
4
|
+
|
|
5
|
+
- Top-level `server/` (or `packages/*` server code) holds DB, services, integrations —
|
|
6
|
+
never imported from client code, enforced with `server-only` + a boundary check, not
|
|
7
|
+
convention. App router in `src/app/`; features as self-contained modules under
|
|
8
|
+
`src/features/<domain>/`; shared pieces in `src/{components,hooks,lib,store,messages}/`.
|
|
9
|
+
Pages stay thin — they compose features.
|
|
10
|
+
- The house convention scopes agent instructions per directory (a short CLAUDE.md/AGENTS.md
|
|
11
|
+
at each boundary-bearing directory) — follow it where a project already does this.
|
|
12
|
+
|
|
13
|
+
## Frontend architecture
|
|
14
|
+
|
|
15
|
+
- Server state → RSC + TanStack Query; URL state → nuqs; ephemeral UI state → Zustand.
|
|
16
|
+
Remote/tenant data is never persisted client-side (rejected for multi-tenant SaaS on
|
|
17
|
+
governance grounds; a confirmed single-tenant/offline product is the only exception —
|
|
18
|
+
ask, don't assume).
|
|
19
|
+
- Next config: `output: 'standalone'`, `cacheComponents: true` (PPR flags no longer
|
|
20
|
+
exist — pinned-facts). Query key factories in non-`'use client'` `.keys.ts` modules so
|
|
21
|
+
RSC pages can prefetch. Server Components by default; `'use client'` only at the lowest
|
|
22
|
+
leaf that needs it. Internal navigation uses `next/link`.
|
|
23
|
+
- Request interception on OpenNext/Cloudflare: check pinned-facts before designing around
|
|
24
|
+
`proxy.ts` — and interception is never the auth boundary (security.md).
|
|
25
|
+
- Dependencies: prefer the native/browser API when it covers the need
|
|
26
|
+
(`Intl.RelativeTimeFormat` over date-fns); self-implement simple behavior by composing
|
|
27
|
+
design-system primitives before adding a library; any non-trivial new dependency needs a
|
|
28
|
+
stated justification and approval. **Why:** self-contained code has no supply-chain,
|
|
29
|
+
licensing, or upgrade surface — MK rejects "library because library".
|
|
30
|
+
|
|
31
|
+
## Design system
|
|
32
|
+
|
|
33
|
+
`vegastack-design-system` owns component choice, tokens, and the do/don't rules;
|
|
34
|
+
first-time wiring is `vegastack-consume`. Consume-don't-extend is a red line (SKILL.md).
|
|
35
|
+
One unresolved item recorded here: touch-target minimum (24px WCAG AA vs 44px mobile-HIG
|
|
36
|
+
both appear in the record) — ask MK when it matters.
|
|
37
|
+
|
|
38
|
+
## UI completeness bar (every real surface, before it's "done")
|
|
39
|
+
|
|
40
|
+
- Full state matrix: loading skeleton shaped like the real content, empty state with
|
|
41
|
+
guidance, errors routed to the specific failure (never swallowed into `{}`), success
|
|
42
|
+
feedback, optimistic updates where a mutation changes visible state.
|
|
43
|
+
- Perceived speed is the named "instant shell" pattern: the layout shell renders
|
|
44
|
+
immediately (RSC + `cacheComponents`), every data region streams in behind a
|
|
45
|
+
content-shaped skeleton — never a blank page or full-page spinner.
|
|
46
|
+
- Systemic fixes: a defect found in one component (scroll leaking through an overlay,
|
|
47
|
+
wrong token) is fixed across the whole family in one sweep, with evidence.
|
|
48
|
+
- Long lists (>~50 rows) virtualize with `@tanstack/react-virtual` (approved — still state
|
|
49
|
+
the justification when adding it).
|
|
50
|
+
- Cloning/rebranding a reference site: strip every trace of the source's provenance (class
|
|
51
|
+
names, asset domains, meta) and verify parity by clicking through as a real user —
|
|
52
|
+
screenshot diffing alone doesn't count.
|
|
53
|
+
|
|
54
|
+
## SEO and metadata (every public-facing app)
|
|
55
|
+
|
|
56
|
+
Every route exports `metadata`/`generateMetadata` — not just the root layout. Public apps
|
|
57
|
+
ship `sitemap.ts` and `robots.ts`; `llms.txt` is generated at build time, never
|
|
58
|
+
hand-maintained; OG images follow the house convention (generated, mono for names/numbers).
|
|
59
|
+
**Why:** MK has demanded "100% SEO" on shipped sites twice — a completeness bar, not an
|
|
60
|
+
enhancement.
|
|
61
|
+
|
|
62
|
+
## Testing — stack-specific taste (whether tests are required: dev.md's `tests:` knob)
|
|
63
|
+
|
|
64
|
+
- Component/a11y tests run in Vitest browser mode with the Playwright provider — jsdom's
|
|
65
|
+
ARIA/layout gaps produce false a11y results and are not trusted.
|
|
66
|
+
- E2E is a walking skeleton: one real happy path (boot → auth → core mutation → verify)
|
|
67
|
+
plus targeted adversarial invariants — not a blanket suite. DB-gated tests are authored
|
|
68
|
+
even when execution is blocked, behind an env flag (`RUN_DB_TESTS=1`); E2E doubles
|
|
69
|
+
implement real ports, never a parallel mock pathway.
|
|
70
|
+
- VRT/demo content is deterministic (no `Date.now()`/`Math.random()`). "100%" means audit
|
|
71
|
+
completeness, never a coverage metric.
|
|
72
|
+
|
|
73
|
+
## Backend / API design
|
|
74
|
+
|
|
75
|
+
- Contract-first: zod schemas are the single source → OpenAPI 3.1 under `/api/v1`,
|
|
76
|
+
camelCase, cursor pagination on every list, RFC 9457 problem-details errors with a
|
|
77
|
+
stable error-code catalog. One contract serves web, Flutter, MCP, and public consumers.
|
|
78
|
+
- Every route: auth before parse, through the shared route-handler wrapper — no
|
|
79
|
+
route-local zod, no raw `request.json()`; responses sanitized (secrets and credential
|
|
80
|
+
references never leave the server). Enforced with a CI ratchet, not review.
|
|
81
|
+
- Return what the view renders — no mega-responses; select columns explicitly.
|
|
82
|
+
- Webhooks over polling; the database is the source of truth. Once provider state lands in
|
|
83
|
+
Postgres via webhook, don't re-poll — and no intermediary "waiting" pages; redirect on
|
|
84
|
+
success and let the rest arrive in the background.
|
|
85
|
+
- Money paths (Stripe): isolated intake (own worker or route), idempotency keys on every
|
|
86
|
+
mutation, event dedupe, append-only ledgers as the single cost source of truth, audit
|
|
87
|
+
events in the same transaction as the business change. Pricing math is deterministic
|
|
88
|
+
code with server-enforced invariants — AI drafts and judges; deterministic code
|
|
89
|
+
calculates and enforces.
|
|
90
|
+
- Centralize the boring: one ID helper, one logger (never `console.log`; request/org
|
|
91
|
+
context auto-injected; never log secrets or PII beyond user IDs), one typed fail-hard
|
|
92
|
+
zod env parser validated at startup.
|
|
93
|
+
- Dead endpoints get deleted, not deprecated-and-kept (exception: a versioned `/api/v1`
|
|
94
|
+
contract consumed by a shipped mobile app — mobile.md).
|
|
95
|
+
- Outbound webhooks to customers: defined event catalog, Standard Webhooks-style signing
|
|
96
|
+
with rotatable secrets, delivery via transactional outbox → queue with retries/backoff,
|
|
97
|
+
auto-disable after N consecutive failures, a replay surface — never fired inline from
|
|
98
|
+
request handlers.
|
|
99
|
+
- Platform-native mentions over plain text: resolve and mention the real entity (Slack
|
|
100
|
+
@mentions, Notion Person fields) instead of rendering names as text.
|
|
101
|
+
- Wizard/checkout flow-state persistence (client store vs server-side draft) is not a
|
|
102
|
+
settled house rule — ask MK when building one.
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
# Freshness contract — architect
|
|
1
|
+
# Freshness contract — dev-architect
|
|
2
2
|
|
|
3
3
|
Most of this skill is durable taste and recorded decisions; it does not go stale on its
|
|
4
|
-
own.
|
|
5
|
-
|
|
4
|
+
own. The decaying surface is `references/pinned-facts.md` — the verified cache behind
|
|
5
|
+
SKILL.md's verify-before-you-recommend protocol — plus the version claims embedded in
|
|
6
|
+
`references/mobile.md` and the fact-adjacent lines the registry's `affected` lists name.
|
|
6
7
|
|
|
7
8
|
## Mechanism
|
|
8
9
|
|
|
@@ -11,9 +12,10 @@ own. Exactly one file decays with the platform landscape: `references/pinned-fac
|
|
|
11
12
|
evidence for anything that changed (fact text, version, date, source). The diffing
|
|
12
13
|
judgment lives in the agent run, not in maintained scripts. The PR is human-reviewed —
|
|
13
14
|
never auto-merged.
|
|
14
|
-
2. **Refresh-on-use (safety net, written into SKILL.md).**
|
|
15
|
-
a pinned fact older than 60 days
|
|
16
|
-
and says so
|
|
15
|
+
2. **Refresh-on-use (safety net, written into SKILL.md).** The verify protocol: a
|
|
16
|
+
recommendation leaning on a pinned fact older than 60 days re-verifies that one fact
|
|
17
|
+
first and says so; an uncached decision-bearing claim is verified against live docs
|
|
18
|
+
before it is recommended. Never bulk-refresh in-session.
|
|
17
19
|
3. **Registry baseline (`sources.json`).** The repo-shared refresh runner
|
|
18
20
|
(`tooling/refresh/refresh-evidence.mjs`) keeps checksum baselines for the critical
|
|
19
21
|
source pages so CI can detect upstream drift deterministically between weekly runs.
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
],
|
|
9
9
|
"defaultChecksumScope": "html-text-v1",
|
|
10
10
|
"offline": "Use cached metadata only; fail closed when a critical entry is missing or older than thresholdDays.",
|
|
11
|
-
"drift": "Any drift requires reading the changed page and a human-reviewed PR updating references/pinned-facts.md
|
|
11
|
+
"drift": "Any drift requires reading the changed page and a human-reviewed PR updating references/pinned-facts.md plus every other file the source's affected list names; never auto-apply.",
|
|
12
12
|
"copyright": "Store claim metadata, URLs, hashes, and concise excerpts only; never archive third-party documentation corpora.",
|
|
13
13
|
"cadence": "weekly scheduled-agent refresh; thresholdDays must be >= 14 (2x cadence) so a single missed run never breaches a threshold"
|
|
14
14
|
},
|
|
@@ -31,7 +31,6 @@
|
|
|
31
31
|
],
|
|
32
32
|
"affected": [
|
|
33
33
|
"references/pinned-facts.md",
|
|
34
|
-
"references/stack.md",
|
|
35
34
|
"references/data.md"
|
|
36
35
|
],
|
|
37
36
|
"checksum": "fda2870b95deffce48dca7f3df3707325b1bc4a2d58a17708ee9220bfba5eba1",
|
|
@@ -102,8 +101,7 @@
|
|
|
102
101
|
],
|
|
103
102
|
"affected": [
|
|
104
103
|
"references/pinned-facts.md",
|
|
105
|
-
"references/security.md"
|
|
106
|
-
"references/stack.md"
|
|
104
|
+
"references/security.md"
|
|
107
105
|
],
|
|
108
106
|
"currentVersion": "1.6.27",
|
|
109
107
|
"versionCheckedAt": "2026-08-12T14:33:11.062Z",
|
|
@@ -129,8 +127,7 @@
|
|
|
129
127
|
],
|
|
130
128
|
"affected": [
|
|
131
129
|
"references/pinned-facts.md",
|
|
132
|
-
"references/ai-agents.md"
|
|
133
|
-
"references/stack.md"
|
|
130
|
+
"references/ai-agents.md"
|
|
134
131
|
],
|
|
135
132
|
"currentVersion": "0.33.2",
|
|
136
133
|
"versionCheckedAt": "2026-08-12T14:33:11.062Z",
|
|
@@ -182,8 +179,7 @@
|
|
|
182
179
|
],
|
|
183
180
|
"affected": [
|
|
184
181
|
"references/pinned-facts.md",
|
|
185
|
-
"references/web.md"
|
|
186
|
-
"references/stack.md"
|
|
182
|
+
"references/web.md"
|
|
187
183
|
],
|
|
188
184
|
"currentVersion": "16.3.0",
|
|
189
185
|
"versionCheckedAt": "2026-08-12T14:33:11.062Z",
|
|
@@ -208,8 +204,7 @@
|
|
|
208
204
|
"jobs"
|
|
209
205
|
],
|
|
210
206
|
"affected": [
|
|
211
|
-
"references/pinned-facts.md"
|
|
212
|
-
"references/ai-agents.md"
|
|
207
|
+
"references/pinned-facts.md"
|
|
213
208
|
],
|
|
214
209
|
"currentVersion": "12.27.0",
|
|
215
210
|
"versionCheckedAt": "2026-08-12T14:33:11.062Z",
|