@vegastack/vegafactory 0.19.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/LICENSE +21 -0
- package/README.md +417 -0
- package/dist/dashboard-artifact.json +21240 -0
- package/dist/index.js +22752 -0
- package/dist/run-wrapper.js +377 -0
- package/package.json +46 -0
- package/skill/dev-architect/SKILL.md +106 -0
- package/skill/dev-architect/agents/openai.yaml +4 -0
- package/skill/dev-architect/references/ai-agents.md +96 -0
- package/skill/dev-architect/references/conventions.md +113 -0
- package/skill/dev-architect/references/data.md +89 -0
- package/skill/dev-architect/references/infra.md +99 -0
- package/skill/dev-architect/references/mobile.md +75 -0
- package/skill/dev-architect/references/pinned-facts.md +133 -0
- package/skill/dev-architect/references/principles.md +117 -0
- package/skill/dev-architect/references/security.md +90 -0
- package/skill/dev-architect/references/stack.md +38 -0
- package/skill/dev-architect/references/web.md +102 -0
- package/skill/dev-architect/refresh/REFRESH.md +31 -0
- package/skill/dev-architect/refresh/sources.json +239 -0
- package/skill/dev-chronicle/SKILL.md +52 -0
- package/skill/dev-chronicle/agents/openai.yaml +4 -0
- package/skill/dev-chronicle/references/conventions.md +113 -0
- package/skill/dev-chronicle/references/styles.md +75 -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 +113 -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 +81 -0
- package/skill/dev-implement/agents/openai.yaml +4 -0
- package/skill/dev-implement/assets/workflows/implement-children.js +12 -0
- package/skill/dev-implement/references/ask-route.md +80 -0
- package/skill/dev-implement/references/changelog-and-chronicle.md +21 -0
- package/skill/dev-implement/references/conventions.md +113 -0
- package/skill/dev-implement/references/ledger-and-resume.md +52 -0
- package/skill/dev-implement/references/parallel-children.md +35 -0
- package/skill/dev-implement/references/worktrees.md +63 -0
- package/skill/dev-implement/refresh/REFRESH.md +3 -0
- package/skill/dev-implement/refresh/sources.json +6 -0
- package/skill/dev-implement/scripts/children.mjs +479 -0
- package/skill/dev-implement/scripts/effective-policy.mjs +694 -0
- package/skill/dev-implement/scripts/evidence-check.mjs +107 -0
- package/skill/dev-implement/scripts/evidence-upload.mjs +181 -0
- package/skill/dev-implement/scripts/learning.mjs +41 -0
- package/skill/dev-implement/scripts/lib/approval.mjs +1182 -0
- package/skill/dev-implement/scripts/lib/gh.mjs +101 -0
- package/skill/dev-implement/scripts/preflight.mjs +153 -0
- package/skill/dev-implement/scripts/questions.mjs +381 -0
- package/skill/dev-implement/scripts/reclaim.mjs +116 -0
- package/skill/dev-implement/scripts/recovery.mjs +213 -0
- package/skill/dev-implement/scripts/worktree.mjs +991 -0
- package/skill/dev-intake/SKILL.md +80 -0
- package/skill/dev-intake/agents/openai.yaml +4 -0
- package/skill/dev-intake/references/ask-route.md +80 -0
- package/skill/dev-intake/references/brief-template.md +89 -0
- package/skill/dev-intake/references/conventions.md +113 -0
- package/skill/dev-intake/refresh/REFRESH.md +3 -0
- package/skill/dev-intake/refresh/sources.json +6 -0
- package/skill/dev-intake/scripts/brief-lint.mjs +87 -0
- package/skill/dev-intake/scripts/lib/approval.mjs +1182 -0
- package/skill/dev-intake/scripts/questions.mjs +381 -0
- package/skill/dev-plan/SKILL.md +54 -0
- package/skill/dev-plan/agents/openai.yaml +4 -0
- package/skill/dev-plan/references/ask-route.md +80 -0
- package/skill/dev-plan/references/conventions.md +113 -0
- package/skill/dev-plan/references/plan-format.md +82 -0
- package/skill/dev-plan/refresh/REFRESH.md +3 -0
- package/skill/dev-plan/refresh/sources.json +6 -0
- package/skill/dev-plan/scripts/lib/approval.mjs +1182 -0
- package/skill/dev-plan/scripts/plan-lint.mjs +319 -0
- package/skill/dev-plan/scripts/questions.mjs +381 -0
- package/skill/dev-review/SKILL.md +76 -0
- package/skill/dev-review/agents/openai.yaml +4 -0
- package/skill/dev-review/assets/review-known-patterns.md.template +32 -0
- package/skill/dev-review/references/conventions.md +113 -0
- package/skill/dev-review/references/cross-agent.md +39 -0
- package/skill/dev-review/references/dispatch-prompts.md +121 -0
- package/skill/dev-review/references/security-axis.md +45 -0
- package/skill/dev-review/refresh/REFRESH.md +5 -0
- package/skill/dev-review/refresh/sources.json +6 -0
- package/skill/dev-setup/SKILL.md +113 -0
- package/skill/dev-setup/agents/openai.yaml +4 -0
- package/skill/dev-setup/assets/agents-section.md.template +24 -0
- package/skill/dev-setup/assets/dev-profile.md.template +102 -0
- package/skill/dev-setup/assets/factory-board.yml.template +162 -0
- package/skill/dev-setup/assets/hooks/decision-nudge.mjs +30 -0
- package/skill/dev-setup/assets/hooks/prompt-skill-mention.mjs +29 -0
- package/skill/dev-setup/assets/hooks/session-end.mjs +14 -0
- package/skill/dev-setup/assets/hooks/session-start.mjs +178 -0
- package/skill/dev-setup/assets/hooks/ship-guard.mjs +738 -0
- package/skill/dev-setup/assets/hooks/skill-activated.mjs +47 -0
- package/skill/dev-setup/assets/hooks/stop-heartbeat.mjs +14 -0
- package/skill/dev-setup/assets/workflows/implement-children.js +12 -0
- package/skill/dev-setup/references/ask-route.md +80 -0
- package/skill/dev-setup/references/conventions.md +113 -0
- package/skill/dev-setup/references/github-app.md +286 -0
- package/skill/dev-setup/references/harness-facts.md +169 -0
- package/skill/dev-setup/references/stack-playbooks.md +124 -0
- package/skill/dev-setup/refresh/REFRESH.md +13 -0
- package/skill/dev-setup/refresh/sources.json +602 -0
- package/skill/dev-setup/scripts/effective-policy.mjs +694 -0
- package/skill/dev-setup/scripts/questions.mjs +381 -0
- package/skill/dev-setup/scripts/ship-policy.mjs +195 -0
- package/skill/dev-ship/SKILL.md +56 -0
- package/skill/dev-ship/agents/openai.yaml +4 -0
- package/skill/dev-ship/references/conventions.md +113 -0
- package/skill/dev-ship/references/runbook.md +72 -0
- package/skill/dev-ship/refresh/REFRESH.md +3 -0
- package/skill/dev-ship/refresh/sources.json +6 -0
- package/skill/dev-ship/scripts/lib/approval.mjs +1182 -0
- package/skill/dev-ship/scripts/ship-gate.mjs +485 -0
- package/skill/dev-status/SKILL.md +56 -0
- package/skill/dev-status/agents/openai.yaml +4 -0
- package/skill/dev-status/references/conventions.md +113 -0
- package/skill/dev-status/refresh/REFRESH.md +3 -0
- package/skill/dev-status/refresh/sources.json +6 -0
- package/skill/dev-status/scripts/effective-policy.mjs +694 -0
- package/skill/dev-status/scripts/status.mjs +311 -0
- package/skill/skill-maintainer/SKILL.md +82 -0
- package/skill/skill-maintainer/agents/openai.yaml +4 -0
- package/skill/skill-maintainer/references/release-ops.md +61 -0
- package/skill/skill-maintainer/references/standards.md +137 -0
- package/skill/skill-maintainer/refresh/REFRESH.md +40 -0
- package/skill/skill-maintainer/refresh/sources.json +103 -0
- package/skill/skill-scan/SKILL.md +59 -0
- package/skill/skill-scan/agents/openai.yaml +4 -0
- package/skill/skill-scan/refresh/REFRESH.md +18 -0
- package/skill/skill-scan/refresh/sources.json +133 -0
- package/skill/skill-scan/scripts/lib/skillspector.mjs +226 -0
- package/skill/skill-scan/scripts/skill-scan.mjs +1002 -0
- package/skill/skillify/SKILL.md +108 -0
- package/skill/skillify/agents/openai.yaml +4 -0
- package/skill/skillify/assets/templates/README.md.template +26 -0
- package/skill/skillify/assets/templates/REFRESH.md.template +16 -0
- package/skill/skillify/assets/templates/SKILL.md.template +27 -0
- package/skill/skillify/assets/templates/evals.json.template +12 -0
- package/skill/skillify/assets/templates/openai.yaml.template +4 -0
- package/skill/skillify/assets/templates/skill.test.ts.template +27 -0
- package/skill/skillify/assets/templates/sources.json.template +6 -0
- package/skill/skillify/assets/templates/trigger-queries.json.template +1 -0
- package/skill/skillify/references/authoring.md +103 -0
- package/skill/skillify/references/eval-playbook.md +112 -0
- package/skill/skillify/refresh/REFRESH.md +23 -0
- package/skill/skillify/refresh/sources.json +6 -0
- package/skill/skillify/scripts/scaffold-skill.mjs +334 -0
- package/skill/skillify/scripts/trigger-check.mjs +209 -0
- package/skill/vegafactory-setup/SKILL.md +77 -0
- package/skill/vegafactory-setup/agents/openai.yaml +4 -0
- package/skill/vegafactory-setup/assets/control-room/boards.md.template +17 -0
- package/skill/vegafactory-setup/assets/control-room/decisions.md.template +5 -0
- package/skill/vegafactory-setup/assets/control-room/group.md.template +44 -0
- package/skill/vegafactory-setup/assets/control-room/onboarding/dispatcher-box.md.template +86 -0
- package/skill/vegafactory-setup/assets/control-room/onboarding/new-repo.md.template +13 -0
- package/skill/vegafactory-setup/assets/control-room/onboarding/new-teammate.md.template +12 -0
- package/skill/vegafactory-setup/assets/control-room/org.md.template +60 -0
- package/skill/vegafactory-setup/assets/control-room/people.csv.template +2 -0
- package/skill/vegafactory-setup/assets/control-room/repos.md.template +7 -0
- package/skill/vegafactory-setup/assets/control-room/rules/CODEOWNERS.template +6 -0
- package/skill/vegafactory-setup/assets/control-room/rules/README.md.template +9 -0
- package/skill/vegafactory-setup/assets/control-room/rules/stats-privacy.md.template +44 -0
- package/skill/vegafactory-setup/assets/control-room/templates/README.md.template +9 -0
- package/skill/vegafactory-setup/references/control-room.md +149 -0
- package/skill/vegafactory-setup/references/conventions.md +113 -0
- package/skill/vegafactory-setup/refresh/REFRESH.md +5 -0
- package/skill/vegafactory-setup/refresh/sources.json +6 -0
- package/skill-integrity.json +252 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# Workflow conventions
|
|
2
|
+
|
|
3
|
+
Artifact authority.
|
|
4
|
+
|
|
5
|
+
Defaults resolve repo, group, then org; locks require explicit org delegation. Repository dispatch/commands never inherit; registers concatenate. Policy/migration uses dev-setup's `scripts/effective-policy.mjs` and vegafactory-setup's control-room reference.
|
|
6
|
+
|
|
7
|
+
## Comment metadata markers
|
|
8
|
+
|
|
9
|
+
Comments open:
|
|
10
|
+
|
|
11
|
+
```markdown
|
|
12
|
+
<!-- vsk:v1 type=<type> rev=<n> [key=value ...] -->
|
|
13
|
+
## <Human title> (v<n>)
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
| type | required keys | instances |
|
|
17
|
+
|---|---|---|
|
|
18
|
+
| `approval` | `scope=<brief\|brief+plan\|plan\|consolidated\|none>` and schema-v2 JSON | one per approval event |
|
|
19
|
+
| `questions` | `rev` | one per ask round; earlier rounds stay as record (dev-setup's `references/ask-route.md`) |
|
|
20
|
+
| `plan` | `rev` | one, edited in place |
|
|
21
|
+
| `ledger` | `branch` | one, edited in place |
|
|
22
|
+
| `evidence` | `rev branch sha` | one, edited in place |
|
|
23
|
+
| `review` | `round sha agent=<claude\|codex> verdict=<clean\|needs-fixes>` | one per review cycle, rounds appended inside |
|
|
24
|
+
| `decision` | — | one per decision proposal |
|
|
25
|
+
| `handback` | — | one per stop event |
|
|
26
|
+
|
|
27
|
+
`rev=<n>` and `(v<n>)` start at 1 only on brief, plan, questions and evidence; other types have neither. Locate by marker, never heading/legacy fallback.
|
|
28
|
+
|
|
29
|
+
## Operator identity
|
|
30
|
+
|
|
31
|
+
Use parenthesized GitHub usernames:
|
|
32
|
+
|
|
33
|
+
- Approval: `Approved by (<username>) on DD-MM-YYYY: "<their words>"`
|
|
34
|
+
- Register line: `- DD-MM-YYYY (<username>) — <decision>`
|
|
35
|
+
|
|
36
|
+
Approval.mjs’s publisher/relay contract lets current-policy provider-envelope publishers attest listed operators’ session words. Other recorders may only relay independently read identical operator-published scoped grants within complete authority history, without lifecycle mutations. Relays inherit source authority/lifecycle; account attestation cannot authenticate off-platform speech.
|
|
37
|
+
|
|
38
|
+
## Scoped approval records
|
|
39
|
+
|
|
40
|
+
Use only dev-implement’s `scripts/lib/approval.mjs` and follow its contract. Refresh current policy and complete GitHub histories. `ArtifactRef={repo,issue,kind,artifactId,rev,digest}` binds brief issue-node or unique plan/protocol comment-node identity, revision and canonical SHA-256.
|
|
41
|
+
|
|
42
|
+
Post exactly one approval comment: matching scope marker, then one fenced JSON `ApprovalRecord={schemaVersion:2,id,operator,scope,source:{kind,ref,quote},artifacts,supersedes,revokes}`. Exclude outer Markdown fences, future alternatives and unresolved source locators; validate the whole body with approval.mjs's `parseApproval`. Source kind is `session` or `github-comment`, with inspectable words. Reuse valid current grants/relays; avoid counterfactual plan-only or redundant approvals. Scope is `brief`, `plan` or `brief+plan`; planning requires brief, implementation both, research execution also its protocol. Empty-artifact revocations remove exact earlier IDs. Conflicts explicitly supersede; newest never wins.
|
|
43
|
+
|
|
44
|
+
Preserve legacy comments. Without writes, inventory refusals/current digests and request reconfirmation. For duplicate canonical plans preserve both identities/bodies and request record-preserving reconciliation; never delete to clear ambiguity. Follow approval.mjs’s exact correction schema, operator-publisher and target checks. Only malformed or demonstrably invalid-source targets qualify, never valid authority or unavailable/inconsistent facts. Resolve source facts first; corrections grant no scope. Exact child checkpoint actions bind one selected code child's branch/ref/base/tasks/files; other actions never substitute.
|
|
45
|
+
|
|
46
|
+
Consolidated parent events bind frozen manifests, canonical artifacts and exact task/action subsets. Use inline UTF-8 or immutable repository/commit/path plus blob hash, never local paths. Canonical `approvalBindings` authorize; requested `recordBinding` only audits. Follow approval.mjs’s preparation/research/recovery provenance, receipts, adapters, counted attempts and fresh admission; retain immutable history and unverified legacy records. Keep checkpoint/private/live/shipping gates separate.
|
|
47
|
+
|
|
48
|
+
Canonicalization normalizes CRLF; its only exceptions are structural plan checkboxes and one validated JSON `{tasks:[{id,evidenceUrls}]}` block between `<!-- vsk:progress:start -->` / `<!-- vsk:progress:end -->`. IDs must exist; URLs are HTTP(S); unknown fields/duplicates refuse. Stable task IDs/order, interfaces, actions, revisions and all other bytes remain scope. Brief/protocol bodies have no mutable fields; fenced examples stay immutable and grant no authority.
|
|
49
|
+
|
|
50
|
+
## Revision markers
|
|
51
|
+
|
|
52
|
+
Scope edits increment marker/heading revisions and append `Revisions: v2 — DD-MM-YYYY: <change>, per (<username>) correction`; preserve earlier lines and obtain fresh approval. Validated progress changes need neither.
|
|
53
|
+
|
|
54
|
+
## Scope classes
|
|
55
|
+
|
|
56
|
+
Intake explains scope; operator overrides:
|
|
57
|
+
|
|
58
|
+
- **`research`** — inquiry; throwaway code allowed, never merged. No branch/PR/changelog; evidence comment contains findings and recommendation.
|
|
59
|
+
- **`quick-build`** — existing flow: draft brief+plan together, approve both, then `ready`.
|
|
60
|
+
- **`full-plan`** — new ground: approve brief, `needs-plan`, separate grounded planning session, `needs-operator`, approve plan, `ready`. Split multiple deliverables into independently classified epic children.
|
|
61
|
+
|
|
62
|
+
Scope ratchet: `dev-plan`.
|
|
63
|
+
|
|
64
|
+
## Labels
|
|
65
|
+
|
|
66
|
+
One state; flips set assignees (colors: dev-setup):
|
|
67
|
+
|
|
68
|
+
| label | meaning | assignee |
|
|
69
|
+
|---|---|---|
|
|
70
|
+
| `needs-operator` | question, brief or plan approval, proposal | the operator |
|
|
71
|
+
| `needs-plan` | brief approved; awaiting planning (full-plan only) | the operator |
|
|
72
|
+
| `ready` | approved — an agent may start | nobody |
|
|
73
|
+
| `working` | claimed; ledger shows live progress | the runner |
|
|
74
|
+
| `for-operator` | done — evidence posted, awaiting operator review | the operator |
|
|
75
|
+
|
|
76
|
+
Modifiers coexist with state: `risky` · scope `research` / `quick-build` / `full-plan` · `epic` (map parents without a native Epic type). Boards mirror states one-way.
|
|
77
|
+
|
|
78
|
+
## Titles, types, hierarchy
|
|
79
|
+
|
|
80
|
+
- **Title prefixes:** issues, branches and PRs use dev.md's `branch:` types plus `research:`; PR title = issue title.
|
|
81
|
+
- **Native issue types/fields:** Feature (feat) · Bug (fix) · Task (docs/chore/refactor/research) · Epic for parents (else label); intake sets Priority/Effort. Scope classes stay labels.
|
|
82
|
+
- **Hierarchy:** epic parent = map only (Destination · Decisions so far · Not clear yet · Out of scope), with native child sub-issues. Issues are work units (brief, approvals, branch, PR, evidence); tasks are checkboxes **only in the plan comment**. Blockers use dependencies; phases use milestones. Only non-epic issues get `ready`.
|
|
83
|
+
|
|
84
|
+
## The ledger
|
|
85
|
+
|
|
86
|
+
One implementation ledger:
|
|
87
|
+
|
|
88
|
+
```markdown
|
|
89
|
+
<!-- vsk:v1 type=ledger branch=<branch> -->
|
|
90
|
+
## Ledger — <branch>
|
|
91
|
+
- <issue>-T<N>: complete (commits <base7>..<head7>[, review clean | K parked])
|
|
92
|
+
- <issue>-T<N>: fix round <R>/3 (<X> addressed, <Y> open — <one-liners>; commits <a>..<b>)
|
|
93
|
+
- Ruling: <what> — <why> — cost if wrong: <cost>
|
|
94
|
+
- <issue>-T<N>: parked — <finding> — Ruling: <why the code stands>
|
|
95
|
+
- Deferred minor: <one-liner>
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
**Resume protocol:** brief → plan comment → ledger → `git log`; then reconcile task IDs, canonical approval history, edited authority, source/evidence, ownership and delivery effects. Preserve completed work/provenance; stale heartbeat is not stop proof. Preparation never implies issue completion. Dev-implement's ledger reference owns recovery detail.
|
|
100
|
+
|
|
101
|
+
## `.vegastack/` workspaces
|
|
102
|
+
|
|
103
|
+
Drafts/reports: `.vegastack/.tmp/<issue-number>-<title-slug>/` (pre-issue: `intake-<slug>`), self-ignored by a `.gitignore` containing `*`. Branch checkouts: root-ignored `.vegastack/.worktrees/<issue-number>-<title-slug>/`; main stays on its default branch. Keep both outside `.git/`. Subagents save full reports and return short status. `<path-to-this-skill>` means SKILL.md’s directory.
|
|
104
|
+
|
|
105
|
+
## Verification gate
|
|
106
|
+
|
|
107
|
+
Prove claims with fresh command output and exit codes; report failures and skips. Delegate only substantial independent parallel work, never your own verification; keep spawn counts low. Guards block machine-verifiable failures (exit 2); heuristics warn. Guards contain no AI inference; unverifiable state fails closed.
|
|
108
|
+
|
|
109
|
+
## Review bindings
|
|
110
|
+
|
|
111
|
+
One fenced JSON each: `{"reviewBinding":{sha,baseSha,scopeDigest,verdict,findings:[{id,status}]}}` in review; `{"adjudication":{sha,reviewCommentId,operator,source:{kind,ref,quote},findings:[{id,disposition,reason}]}}` in evidence. Use full commit IDs and canonical-plan scopeDigest; status=open/resolved; disposition=accept-risk. Every open finding requires same-review operator acceptance. dev-ship’s README defines source checks. No prose exceptions.
|
|
112
|
+
|
|
113
|
+
Communicate starts/findings/direction plainly; self-contained outcomes include paths and remaining checks. Avoid invented labels/arrows; visualize usefully. Challenge ambiguity with options; never guess silently.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Data — Postgres, tenancy, storage, caching
|
|
2
|
+
|
|
3
|
+
## Database
|
|
4
|
+
|
|
5
|
+
- PostgreSQL, always managed by us (a PlanetScale Postgres server or self-hosted
|
|
6
|
+
Hetzner-class) — never Neon. Behind Hyperdrive, target the highest Postgres major
|
|
7
|
+
Hyperdrive supports (pinned-facts — PG 18 is a known trap). Drizzle ORM with the single
|
|
8
|
+
`postgres-js` driver — never mix in `pg`. Stay on GA/stable majors of core DB deps;
|
|
9
|
+
verify vendor version-support claims per SKILL.md's verify protocol before locking a
|
|
10
|
+
decision.
|
|
11
|
+
- From Workers: Hyperdrive binding + per-request client (`prepare: false, max: 1`,
|
|
12
|
+
request-scoped via the execution context) — a module-level pool in a Worker or Durable
|
|
13
|
+
Object is a bug, not a style choice (workerd forbids cross-request I/O). One Hyperdrive
|
|
14
|
+
per environment shared across services hitting the same database — never one per
|
|
15
|
+
service. On long-running Node services (Docker), pool normally.
|
|
16
|
+
- Migrations run via CI only, never pushed from a dev machine — with one loud exception:
|
|
17
|
+
pre-launch databases with zero real users get clean resets instead of migration chains
|
|
18
|
+
(principles.md). Runners apply in journal order, idempotent on re-run. Iterate schema
|
|
19
|
+
with `db:push` during development; run `db:generate` exactly once right before shipping
|
|
20
|
+
— repeated generates mid-iteration create conflicting DDL.
|
|
21
|
+
|
|
22
|
+
## Multi-tenancy
|
|
23
|
+
|
|
24
|
+
- Shared schema with RLS, not database-per-tenant: every tenant-scoped table (and every
|
|
25
|
+
partition) gets `ENABLE` + `FORCE` ROW LEVEL SECURITY, driven by exactly one fail-closed
|
|
26
|
+
GUC accessor (`NULLIF(current_setting('app.current_org_id', true), '')::uuid`), defined
|
|
27
|
+
in one idempotent migration location.
|
|
28
|
+
- RLS is one layer, never the only layer: every query also scopes explicitly by
|
|
29
|
+
`org_id`/`workspace_id` in the data-access layer. Two roles — the app role has no
|
|
30
|
+
`BYPASSRLS`; a separate system role does. `withOrgContext`/`withSystemContext` (or
|
|
31
|
+
equivalent) are the only query entry points; the raw client is never exported. **Why:**
|
|
32
|
+
RLS misses TimescaleDB chunks and misconfigurations fail open; two independent layers
|
|
33
|
+
fail closed.
|
|
34
|
+
- Tenant identity comes from the authenticated principal, never client-supplied fields —
|
|
35
|
+
the IDOR precedent and rule live in security.md.
|
|
36
|
+
- Better Auth's organization plugin owns the workspace/member/invitation schema
|
|
37
|
+
(security.md); its columns stay snake_case as generated, with native `uuid` columns —
|
|
38
|
+
Better Auth does not force text IDs.
|
|
39
|
+
|
|
40
|
+
## Caching
|
|
41
|
+
|
|
42
|
+
- No cache layer by default: rate limiting, dedupe, and most "cache" needs are
|
|
43
|
+
Postgres-native. Workers KV only with a named trigger; any Redis-class store is
|
|
44
|
+
optional and **never correctness-bearing**.
|
|
45
|
+
- Never let auth, role, or permission data live in a cache long enough to serve stale
|
|
46
|
+
permissions — a revoked member seeing tenant data is a security bug, not a staleness
|
|
47
|
+
bug. Anything cached has a defined cache-outage story (fall back to DB, never
|
|
48
|
+
stale-forever).
|
|
49
|
+
|
|
50
|
+
## Search, knowledge, files
|
|
51
|
+
|
|
52
|
+
- Search and embeddings live in Postgres itself: `STORED` generated `tsvector` + GIN for
|
|
53
|
+
full-text; pgvector (`halfvec` + HNSW, `hnsw.iterative_scan = relaxed_order`) for
|
|
54
|
+
embeddings; hybrid fusion via RRF (k=60 starting constant). Embedding default: BGE-M3
|
|
55
|
+
self-hosted; bulk embedding calls skip the AI Gateway (the one carve-out from the
|
|
56
|
+
blanket gateway rule). No dedicated vector DB or SaaS search service.
|
|
57
|
+
- Object storage: R2 by default, always behind an S3-compatible layer so AWS S3/Azure
|
|
58
|
+
Blob/MinIO work for licensed self-hosted deployments. Short-lived scoped access
|
|
59
|
+
(presigned), size/type validation on upload. Keys never expose raw user/workspace IDs —
|
|
60
|
+
documented prefix + nanoid (`wl_`, `ua_` style).
|
|
61
|
+
- Blob GC deletes the storage object before the DB reference row — a crash mid-delete
|
|
62
|
+
must never leave a live dangling reference.
|
|
63
|
+
- TimescaleDB is opportunistic, never required: feature-detect and fall back to native
|
|
64
|
+
`PARTITION BY RANGE` + BRIN in the same migration, so self-hosted installs work on
|
|
65
|
+
plain Postgres.
|
|
66
|
+
|
|
67
|
+
## Schema discipline
|
|
68
|
+
|
|
69
|
+
- Extend an existing table before creating a new one; when two tables serve the same job,
|
|
70
|
+
merge. Keep sync (`*_change_log`), audit (`audit_log`), and versioning (`*_revisions`)
|
|
71
|
+
as three separate, non-overlapping tables — never substitute one for another.
|
|
72
|
+
- IDs: one global helper — UUIDs (v7 where ordering matters) internal, prefixed nanoids
|
|
73
|
+
public-facing. Timestamps `timestamptz` UTC, rendered in the user's timezone; money in
|
|
74
|
+
integer minor units; durations integer milliseconds. Prefer checked text over Postgres
|
|
75
|
+
enums for evolving vocabularies.
|
|
76
|
+
- Secrets and PII never sit in plaintext columns (including inside JSONB) —
|
|
77
|
+
broker-wrapped envelope encryption only (security.md).
|
|
78
|
+
- JSONB-on-row vs. dedicated table has no house default — MK has ruled both ways by
|
|
79
|
+
context. Present the tradeoff (volume, query needs, audit requirements) and ask.
|
|
80
|
+
|
|
81
|
+
## Backups and recovery
|
|
82
|
+
|
|
83
|
+
- Self-managed Postgres ships with WAL archiving + scheduled base backups from day one —
|
|
84
|
+
a database without a tested restore path is not production, whatever else is true.
|
|
85
|
+
- A restore runbook (where backups live, how to restore, measured time) is a phase-0
|
|
86
|
+
deliverable for any live product; note RPO/RTO in dev.md's `## Architecture`. Test the
|
|
87
|
+
restore, don't assume it.
|
|
88
|
+
- R2/object storage: no bucket versioning by default — deletion protection is the
|
|
89
|
+
object-before-row GC discipline plus lifecycle rules, planned explicitly.
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Infra — hosting, CI cost, observability
|
|
2
|
+
|
|
3
|
+
## Hosting targets
|
|
4
|
+
|
|
5
|
+
Two sanctioned targets, recorded in dev.md's `## Architecture`:
|
|
6
|
+
|
|
7
|
+
- **Cloudflare Workers via OpenNext** — the default for public web products. Once
|
|
8
|
+
committed to Cloudflare, never stand up a parallel Vercel deploy path (deploy paths
|
|
9
|
+
drift); shared packages must still *work* on Vercel for downstream consumers —
|
|
10
|
+
portability, not a deploy target.
|
|
11
|
+
- **Self-managed servers** (Hetzner-class, Docker; Coolify for push-to-deploy) — when
|
|
12
|
+
self-hosting is a product requirement, the workload needs long-lived processes (EVE,
|
|
13
|
+
heavy workers), or platform independence justifies ~30 min/month of real ops.
|
|
14
|
+
- Vercel only by explicit, recorded per-project exception (e.g. EVE-hosted workloads).
|
|
15
|
+
Internal/admin apps needing no edge features may run plain `next start` in Docker —
|
|
16
|
+
OpenNext is the default, not a ritual.
|
|
17
|
+
|
|
18
|
+
## Cloudflare discipline
|
|
19
|
+
|
|
20
|
+
- Provision only what the current phase uses. Queues, KV, Durable Objects, Workflows are
|
|
21
|
+
trigger-gated — DO when live collaboration actually ships, Queues when webhook/event
|
|
22
|
+
volume is real — never scaffolded ahead of need. Delete stale Workers, Hyperdrive
|
|
23
|
+
configs, and buckets, with an explicit create/delete accounting first.
|
|
24
|
+
- Multi-env via the Workers environments feature (`env.*`) — never separate top-level
|
|
25
|
+
Workers per environment; environments are `dev` / `preview` / `production`, and the
|
|
26
|
+
`staging` git branch deploys to `preview`. One Hyperdrive per environment, shared by
|
|
27
|
+
every service hitting the same database. Naming: hyphen-only; purge inconsistent legacy
|
|
28
|
+
names.
|
|
29
|
+
- Domains: production on `vegastack.com`; non-prod under `*.vegastack.dev`. Every Worker
|
|
30
|
+
sets `workers_dev: false` + `custom_domain: true` — the default `*.workers.dev` origin
|
|
31
|
+
bypasses Cloudflare Access, exposing a gated Worker unauthenticated (security, not
|
|
32
|
+
cosmetics). Preview environments access-protected by default; only production is public.
|
|
33
|
+
- Secrets per environment (`wrangler secret put X --env production`). Local env files:
|
|
34
|
+
`.env` feeds `next dev`, `.dev.vars` feeds `wrangler dev` — both gitignored, both with
|
|
35
|
+
committed `.example` companions.
|
|
36
|
+
- No Cloudflare Images — optimize with `sharp` at build/upload time and serve from R2 (the
|
|
37
|
+
paid add-on solves a problem `sharp` + free egress already solve).
|
|
38
|
+
- Runtime constraints are architectural facts: no TCP clients, per-request DB connections
|
|
39
|
+
(data.md), and OpenNext trails vanilla Next.js — check OpenNext docs per feature
|
|
40
|
+
(current adapter caveats: pinned-facts).
|
|
41
|
+
- Edge/CDN caching never bypasses live authorization — revoked, expired, or
|
|
42
|
+
password-protected content is re-checked even when the artifact is cached.
|
|
43
|
+
- Cloudflare Tunnel is the default for exposing self-hosted services and remote dev
|
|
44
|
+
previews (already paid for). Cloudflare Access gates paths by data sensitivity with
|
|
45
|
+
email allowlists — not one site-wide gate.
|
|
46
|
+
|
|
47
|
+
## Self-managed discipline
|
|
48
|
+
|
|
49
|
+
- Containers hardened: non-root user, `cap_drop: [ALL]`, `read_only: true` where runtime
|
|
50
|
+
paths allow; healthchecks on every service. Migrations and storage provisioning run in
|
|
51
|
+
the app container's own entrypoint under a Postgres advisory lock (safe when replicas
|
|
52
|
+
race on boot) — not a separate bootstrap deployable unless a project records why.
|
|
53
|
+
- Ship `docker compose up` as the self-host story: bundle only Postgres + MinIO-class
|
|
54
|
+
essentials; everything else (vector store, gateway, vault) is connect-your-own.
|
|
55
|
+
- Server sizing: SSD, compute, and RAM over disk capacity, within the budget the architecture
|
|
56
|
+
owner states for that server (ask if none stated — don't guess); Coolify's own footprint:
|
|
57
|
+
pinned-facts. Cloud infra beyond Cloudflare goes through Terraform, IAM scoped narrowly per
|
|
58
|
+
purpose.
|
|
59
|
+
- Any infra cleanup (disks, stale resources, runners) needs explicit authorization first,
|
|
60
|
+
scoped to verified-stale items — never blanket cleanup.
|
|
61
|
+
|
|
62
|
+
## CI cost and verification (workflow gates and ship mechanics live in dev.md)
|
|
63
|
+
|
|
64
|
+
- CI is cost-managed, not maximal: path-condition expensive jobs so docs-only changes skip
|
|
65
|
+
them; push heavy verification into local hooks and self-hosted runners; hosted Actions
|
|
66
|
+
minutes are a tracked budget. Verification is local-first — CI verifies it happened via
|
|
67
|
+
a committed receipt bound to the git tree hash rather than re-executing browser suites;
|
|
68
|
+
a receipt is attestation, not proof — skipping a gate becomes visible, not impossible.
|
|
69
|
+
- Wire every architectural guard script (import boundaries, runtime gravity, route-wrapper
|
|
70
|
+
ratchet) into the one composed check command — a separate script someone forgets to run
|
|
71
|
+
doesn't exist.
|
|
72
|
+
- Green CI is necessary, never sufficient: a unit is done after a real
|
|
73
|
+
boot → auth → reach → mutate → verify pass against live infra. On CI failure: diagnose
|
|
74
|
+
and report the root cause first; fix second.
|
|
75
|
+
|
|
76
|
+
## Observability (small-team baseline)
|
|
77
|
+
|
|
78
|
+
- Structured JSON logs (pino) to stdout with OTel-shaped fields (trace/request/org context
|
|
79
|
+
auto-injected) — OTel-compatible by convention now; the full OTel SDK/collector only
|
|
80
|
+
when cross-service trace correlation becomes a real pain.
|
|
81
|
+
- The append-only Postgres event log is the authoritative telemetry source; metrics/log
|
|
82
|
+
tables are derived and disposable (30-day raw, 13-month rollups, compress after ~7 days;
|
|
83
|
+
TimescaleDB opportunistic with partition+BRIN fallback).
|
|
84
|
+
- On Cloudflare, use the built-in free tier first — Workers Logs and the analytics
|
|
85
|
+
dashboard (current limits and billing dates: pinned-facts).
|
|
86
|
+
- Alerting honest to team size: an uptime monitor (Uptime Kuma-class) + a cron checking
|
|
87
|
+
error-rate thresholds in the event table posting to Slack, plus a dead-man's-switch ping
|
|
88
|
+
for silent job failures. No paging/SLO/on-call ceremony — deliberately undefined until
|
|
89
|
+
the team needs it; propose per project, don't invent doctrine.
|
|
90
|
+
|
|
91
|
+
## Incidents
|
|
92
|
+
|
|
93
|
+
- Active production incident: diagnose first (root cause with evidence), fix second — the
|
|
94
|
+
standing rule applies under pressure too. Rolling back a deploy IS a deploy: it needs the
|
|
95
|
+
operator's go-ahead — bring them the evidence and the recommended rollback; mitigation
|
|
96
|
+
that doesn't deploy (feature-level disable, traffic block) can proceed and be reported.
|
|
97
|
+
- Every real incident gets a short postmortem in the project's `docs/postmortems/`: what
|
|
98
|
+
happened, root cause, the guard that now prevents it. An incident that doesn't change a
|
|
99
|
+
rule or a check will repeat.
|
|
@@ -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 the architecture owner has not ratified are tagged
|
|
13
|
+
"(inferred)" — confirm on first 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 the architecture owner rather than assume): push-notification provider,
|
|
75
|
+
offline/sync expectations per product, store-release cadence.
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# Pinned platform facts
|
|
2
|
+
|
|
3
|
+
Dated, source-verified facts that change architecture decisions and that models routinely
|
|
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
|
|
6
|
+
itself — the weekly refresh (see refresh/REFRESH.md) re-verifies it. When a recommendation
|
|
7
|
+
leans on a fact older than 60 days, re-verify that one fact against its source first.
|
|
8
|
+
|
|
9
|
+
Facts carry their own verification dates — sections verified 2026-08-12 unless a
|
|
10
|
+
bullet says otherwise; Better Auth and EVE re-verified 2026-08-29.
|
|
11
|
+
|
|
12
|
+
## Cloudflare
|
|
13
|
+
|
|
14
|
+
- **R2 egress is $0 at any volume.** A 500GB-stored / 2TB-served workload is ~$191/mo on
|
|
15
|
+
S3 vs ~$7.50/mo on R2. Reaching for S3+CloudFront "to control egress" solves a problem R2
|
|
16
|
+
doesn't have. Lifecycle rules, bucket locks, event notifications, and Infrequent Access
|
|
17
|
+
are all live — note IA transitions are one-way via lifecycle (IA→Standard needs a manual
|
|
18
|
+
CopyObject). [developers.cloudflare.com/r2/pricing]
|
|
19
|
+
- **Hyperdrive supports PostgreSQL 9.0–17.x — PG 18 is NOT supported.** Target Postgres 17
|
|
20
|
+
for any Hyperdrive-fronted database; re-check the supported-versions page before ever
|
|
21
|
+
moving to 18. Hyperdrive also supports MySQL (GA 2026-08-07) and private DBs via Workers
|
|
22
|
+
VPC. [developers.cloudflare.com/hyperdrive/reference/supported-databases-and-features]
|
|
23
|
+
- **Durable Objects default to SQLite storage** (real SQL, transactions, point-in-time
|
|
24
|
+
recovery), and **hibernating WebSocket DOs bill ~$0 while idle** — one-DO-per-room is
|
|
25
|
+
cost-competitive with Redis+socket.io for mostly-idle connections.
|
|
26
|
+
[developers.cloudflare.com/durable-objects]
|
|
27
|
+
- **Workflows: 10,000 steps default / 25,000 max, 365-day sleeps — and per-step billing
|
|
28
|
+
since 2026-08-10.** High-step-count designs now have a real cost dimension.
|
|
29
|
+
[developers.cloudflare.com/workflows]
|
|
30
|
+
- **Browser Rendering is metered by duration AND concurrency** ($0.09/browser-hour + $2 per
|
|
31
|
+
extra concurrent browser) — batch scraping through a queue; it is not free headless Chrome.
|
|
32
|
+
[developers.cloudflare.com/browser-rendering]
|
|
33
|
+
- **R2/KV/Workflows event notifications route through Queues "event subscriptions"** — a
|
|
34
|
+
Queue consumer covers platform state changes; don't build a bespoke webhook receiver.
|
|
35
|
+
- **D1 read replication only helps via the Sessions API** (`withSession(bookmark)`);
|
|
36
|
+
without it every query still hits the primary.
|
|
37
|
+
|
|
38
|
+
## Next.js (16.3, released 2026-08-03)
|
|
39
|
+
|
|
40
|
+
- **PPR flags are gone** — `experimental.ppr` no longer exists; partial prerendering is
|
|
41
|
+
part of `cacheComponents: true` (which also replaced `dynamicIO`). [nextjs.org/blog]
|
|
42
|
+
- **`middleware.ts` is replaced by `proxy.ts` running on Node** — full fs/crypto/native
|
|
43
|
+
package access in request interception.
|
|
44
|
+
- **`proxy.ts`/Node middleware does NOT work on OpenNext Cloudflare as of 2026-08** (open
|
|
45
|
+
issues opennextjs-cloudflare#962/#1277, workers-sdk#13755/#13937) — don't design a
|
|
46
|
+
Cloudflare-hosted feature around `proxy.ts`; re-check the trackers before assuming it
|
|
47
|
+
shipped. Turbopack is supported since adapter v1.15.0 (the old breakage is fixed;
|
|
48
|
+
re-verify only on older pins).
|
|
49
|
+
- **The Adapter API is stable since 16.2** — Vercel's adapter and Cloudflare's OpenNext
|
|
50
|
+
adapter share the same public contract, but Cloudflare's still trails on newest features;
|
|
51
|
+
check the deployment feature matrix per feature, don't assume parity.
|
|
52
|
+
[nextjs.org/docs/app/guides/deploying-to-platforms]
|
|
53
|
+
|
|
54
|
+
## Cloudflare Workers hard limits
|
|
55
|
+
|
|
56
|
+
- **Memory 128MB per isolate (hard), CPU 30s default / 5min max (configurable), 1000
|
|
57
|
+
subrequests per request (paid).** Heavy transforms (image processing, big parses)
|
|
58
|
+
belong in a container/worker tier, not a Worker. Workers Logs free tier: 200k
|
|
59
|
+
events/day, 3-day retention; automatic tracing starts billing 2026-10-01; OTLP export
|
|
60
|
+
needs Workers Paid. [developers.cloudflare.com/workers/platform/limits]
|
|
61
|
+
|
|
62
|
+
## Better Auth (1.7.2, 2026-08-29)
|
|
63
|
+
|
|
64
|
+
- **1.7 is stable** — 1.7.0 shipped 2026-08-18, current 1.7.2 (2026-08-26, npm latest).
|
|
65
|
+
The former 1.6.x hold is retired; adopt 1.7.x via the official migration steps. Notable
|
|
66
|
+
1.7.0 breaks beyond the bullets below: accounts rekeyed on `(issuer, accountId)` with a
|
|
67
|
+
migration backfill; `validAudiences` → `resources` + `oauthClientResource`;
|
|
68
|
+
`experimental.joins` → `advanced.database.joins`; generic OAuth rewritten on OAuth 2.1
|
|
69
|
+
defaults. [github.com/better-auth releases, verified 2026-08-29]
|
|
70
|
+
- **The MCP plugin lives in `@better-auth/mcp` since 1.7.0** — requires
|
|
71
|
+
`@better-auth/cimd` and the `jwt()` plugin; `withMcpAuth` → `requireMcpAuth`,
|
|
72
|
+
`mcpHandler` → `createMcpProtectedRequestHandler`; options are flat, no `oidcConfig`
|
|
73
|
+
nesting. [releases/tag/v1.7.0]
|
|
74
|
+
- **SAML IdP-initiated sign-in is default-off since 1.7.0** (`saml.allowIdpInitiated`
|
|
75
|
+
defaults to false); opt back in explicitly only where the IdP flow is required.
|
|
76
|
+
[releases/tag/v1.7.0, verified 2026-08-29]
|
|
77
|
+
- **The organizations plugin models teams, invitations, and custom RBAC end-to-end**
|
|
78
|
+
(`teams: { enabled: true }`, `inviteMember` with `teamId`, `createAccessControl`) —
|
|
79
|
+
unchanged in 1.7 (SCIM was decoupled from it; irrelevant unless SCIM is used).
|
|
80
|
+
[better-auth.com/docs, verified 2026-08-29]
|
|
81
|
+
- **The apiKey plugin is the standalone `@better-auth/api-key` package** (lockstep
|
|
82
|
+
1.7.2) — import from `@better-auth/api-key`, not `better-auth/plugins` (core's exports
|
|
83
|
+
no longer carry it). Default to the plugin for new projects; the flagship platform's
|
|
84
|
+
native implementation is a recorded project decision, not the house default. The
|
|
85
|
+
`bearer` plugin stays in core and covers token session transport (the mobile/Flutter
|
|
86
|
+
mechanism). [better-auth.com/docs/plugins/api-key, verified 2026-08-29]
|
|
87
|
+
- **`twoFactor` supports `allowPasswordless: true`** for users without password accounts
|
|
88
|
+
(passkey/OAuth/magic-link signups). Since 1.7.0, `enableTwoFactor` takes and returns a
|
|
89
|
+
discriminated `method: "otp" | "totp"` (default totp) — pass `method: "otp"` for OTP
|
|
90
|
+
enrollment.
|
|
91
|
+
|
|
92
|
+
## Claude API (verified 03-09-2026)
|
|
93
|
+
|
|
94
|
+
- **Thinking blocks bind to their conversation prefix on Claude Fable 5.1**: replaying one after
|
|
95
|
+
the system prompt, tools, or an earlier message changed returns a 400 for accounts created on
|
|
96
|
+
or after 31-08-2026 (future models: everyone); keep product agent loops append-only.
|
|
97
|
+
**Assistant prefill on the last turn is a 400 from Claude 4.6 onward** — use structured outputs.
|
|
98
|
+
[platform.claude.com/docs/en/build-with-claude/prompt-engineering]
|
|
99
|
+
|
|
100
|
+
## Agents & jobs
|
|
101
|
+
|
|
102
|
+
- **EVE (`eve` on npm, github.com/vercel/eve) is Vercel's durable-agent framework — v0.47.3
|
|
103
|
+
(2026-08-28), still beta/pre-GA, shipping multiple releases per day; pin behavior, not
|
|
104
|
+
minor versions.** Filesystem-first agents; every session a durable, resumable
|
|
105
|
+
workflow. [vercel.com/docs/eve]
|
|
106
|
+
- **Self-hosted EVE durability (`@workflow/world-postgres`, stable 4.3.x) explicitly
|
|
107
|
+
requires a long-lived worker process — "not compatible with serverless platforms".**
|
|
108
|
+
The 5.0.0-beta channel exists; don't pin it without a documented reason. Internally it
|
|
109
|
+
uses graphile-worker — it is not pg-boss and doesn't replace it.
|
|
110
|
+
[workflow-sdk.dev/worlds/postgres]
|
|
111
|
+
- **pg-boss is at 12.x** — Postgres-native (`SKIP LOCKED`), no Redis. The right default
|
|
112
|
+
for simple background jobs/cron on this stack; BullMQ only when a genuinely complex job
|
|
113
|
+
graph (flows, dependencies, rate-limited pipelines) demands Redis. [npm: pg-boss]
|
|
114
|
+
- **trigger.dev v4 is Apache-2.0 and self-hostable free with unlimited runs** — the
|
|
115
|
+
credible escape hatch when a job needs multi-hour runtimes off-platform. [trigger.dev]
|
|
116
|
+
|
|
117
|
+
## Databases & mobile
|
|
118
|
+
|
|
119
|
+
- **PlanetScale Postgres is built on Neki, not Vitess** — a newer product (GA 2025-09);
|
|
120
|
+
don't transfer Vitess/MySQL assumptions. No free tier (the free Hobby plan died April
|
|
121
|
+
2024); Postgres pricing is SKU-based from PS-5 non-HA at $5/mo, HA from ~$15-50/mo.
|
|
122
|
+
($39/mo figures seen elsewhere are the Vitess/MySQL PS-10 tier — a different product.)
|
|
123
|
+
[planetscale.com/pricing]
|
|
124
|
+
- **Flutter's default renderer is Impeller on iOS, Android, and macOS** — "disable
|
|
125
|
+
Impeller on Android" guidance is stale. [docs.flutter.dev]
|
|
126
|
+
|
|
127
|
+
## Self-hosting
|
|
128
|
+
|
|
129
|
+
- **Coolify needs ~2GB RAM for its own control plane and requires active patching** —
|
|
130
|
+
two critical-CVE waves in 2026 alone (Jan: beta.445/451; Jun-Jul: CVE-2026-34047/49/50,
|
|
131
|
+
fixed in beta.471) — a recurring pattern, not a closed incident. Size Hetzner VMs
|
|
132
|
+
accordingly (CX22/4GB is the floor for Coolify + one small app); ~30 min/month real
|
|
133
|
+
maintenance, not zero. [coolify.io]
|
|
@@ -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 the
|
|
81
|
+
architecture owner with a 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, the architecture owner signs off on the fix. **production-gate** — fixed
|
|
92
|
+
before the surface serves real users; fine behind pre-launch. **consider** — advisory; log
|
|
93
|
+
and move on. Never round up; judge severity against the project's Architecture facts —
|
|
94
|
+
never surface 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; the architecture owner and the team decide. A departure from a
|
|
103
|
+
recommendation becomes one dated accepted-risk line proposed for the register, reported
|
|
104
|
+
honestly in later reviews — never 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 the architecture owner 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 the architecture
|
|
117
|
+
owner's sign-off; the register plus the issue briefs are the handover record.
|