Thirteen tasks, each ending in a testable deliverable and a commit.
Also drops --log-level from the spec: the tool's whole output is what it is
telling the operator, and a level that could hide a key warning is worth not
having.
vantagectl/Dockerfile follows the repo's per-module convention rather than
living under deploy/docker.
verify's live check needs AES-GCM open, so the cipher primitives move to
shared/cryptobox and services/crypto.go delegates, rather than a second
copy of the cipher existing in another module.
Standalone vantagectl CLI (cobra, own module) that dumps and restores a
whole Vantage MongoDB database, stamping a sha256 fingerprint of
KEY_ENCRYPTION_KEY into the manifest so a restore cannot silently produce
a database whose secrets are unreadable.
The key itself never enters the archive.
createToken's catch-all answered 400 for every unmatched error, so a
database failure reported itself as the caller's malformed request. Found
in review of Task 7.
The plan's Middleware called sessionFromToken even when sessionFromCookie
had already answered a rejected cookie, putting two JSON bodies on the
wire for the ordinary expired-session case. Found in review of Task 5.
Twelve tasks from model through middleware, scope enforcement, endpoints,
web UI, generated OpenAPI and documentation. Verification is build plus
curl and UI checks rather than test cycles, matching a repository with no
Go test harness beyond shared/mail.
Adds the approved design for personal access tokens on the control plane
REST API, and for the generated OpenAPI 3.1 document served as a Scalar
reference page.
Tokens fall back into the existing session middleware rather than getting
their own route group, so every handler, role guard and audit call works
unchanged. Scope enforcement derives from the registered route pattern and
fails closed, with a boot-time check for unmapped routes.
A Terraform provider is deliberately left to a follow-on spec.
Both plans now verify by build, vet and manual checks written into the
tasks. Spec verification sections updated to match so they no longer
describe tests that will not be written.
Agents enumerate Docker containers, compose stacks and systemd services;
start/stop/restart and bounded log snapshots from the UI.
Sub-project B, Linux only. Live log following stays in the console.
17 tasks, TDD where the logic is pure. Corrects two spec claims:
the server reads features via License.HasFeature rather than admin's
entitlement directly, and shared/mail/render_test.go does not exist.
Agents report installed packages; the control plane matches them against
trivy-db and raises findings that link to the existing ApplyUpdatesCmd
patching path.
Scoped to sub-project A, Linux only. Container registry, image scanning
and compliance baselines are separate specs.
Implements spec 7 tasks 2-10 on top of the six-plan payload from task 1.
Admin: plans re-keyed on (deployment, tier); new catalogue collection holds
every Paddle price ID (one row per priceable component); new entitlements
collection holds desired beside granted. admin/internal/catalogue owns both
folds — entitlement to licence limits, and entitlement to Paddle line items —
so the base allowance is subtracted in exactly one place. licensing.Issue now
snapshots the instance's granted entitlement, never desired. Free is enforced
per account AND deployment. Staff endpoints for plans, catalogue and
entitlements; Free self-hosted can be claimed and renewed on its annual term;
the reaper stays cloud-only.
Server: enforces the monitor cap, audit-log retention (daily sweep, skips
Unlimited and lapsed instances), and gates the OIDC callback. Unset limits are
filled from the seed plan at the single decode site so old blobs never read as
zero.
Frontends: adminsite gains a catalogue price-ID editor, six-plan allowance
screen, and a catalogue-driven PlanConfigurator mounted on the staff instance
page. web shows monitors, audit retention and support level on the licence page.
Docs: CLAUDE.md, spec index and plan 5 preamble updated.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Ten tasks, each ending in something independently verifiable. The plan
stops at the Paddle boundary on purpose: spec 7 lands before plan 5, so
there is no client, no webhook and no checkout here, and the configurator
is built as a component mounted for staff first rather than as a customer
screen with nothing behind it.
Corrects two things the spec got wrong about the control plane. Feature
gating is already built and mounted, so Free tenants have already lost the
console and no customer email is owed. The only real gap is that
HandleOIDCCallback lacks the check HandleOIDCStart already has, which is
the half that completes a sign-in.
Adds the Free self-hosted lifecycle the spec called for and the first draft
of the plan missed: linking issues nothing today, and renewInstance
hardcodes a monthly term that would hand a self-hosted install a one-month
licence.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Two deployments times three tiers, servers metered per month, console and
SSO opted into individually. plans is re-keyed on (deployment, tier); every
Paddle price ID moves out of plans into a new catalogue collection; a new
entitlements collection holds desired beside granted, and a licence is only
ever signed from granted.
Spec 5's plan is revised rather than followed: it assumes one price per
subscription and a metered plan has three or more. Nothing of it has
shipped, so the revision costs a rewrite of an unstarted plan.
Free stops being cloud-only by construction, which means the plan/instance
deployment comparison in licensing.Issue no longer enforces it and
checkFreeLimit has to count per deployment.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Ten tasks: cloudprov, instance creation, renewal, the notice sweep, the
reaper, the reconciler tie-in, the HQ and marketing UI, the sitesvc
cutover, and an end-to-end verification.
The reaper sweeps once at boot as inject's reconciler does, which is what
makes it observable at all — the ticker is hourly and deletion is
measured in days.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Seven tasks: the index swap, the hq fields, the three scoped lookups,
removing admin's unscoped control-plane login, and an end-to-end
verification that two users sharing one address sign in to different
instances.
Also corrects the spec's phase list, which claimed phase 1 projects the
creator as owner. Projection needs instance creation, which is phase 2.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
An account has people, and those people belong to several cloud
instances. That requires dropping the global unique index on users.email
for a compound (instance_id, email), scoping the two unscoped lookups
that made the global index load-bearing, and projecting HQ users into
instances as real control-plane users.
Self-hosted instances are never projected into; their users stay local.
Restructured into three phases: identity, creation and lifecycle,
membership.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Separates having an account from having an instance. Signup creates only
the HQ account; the customer then creates a Free cloud instance from the
portal, which provisions the control-plane instance, the admin_instances
row and a Free licence in one path.
Supersedes spec 5's signup-migration section.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Publishes adminsite on 3004 -- 3000 is web, 3003 is the marketing site since
the port shuffle -- and adds the sixth CI image.
CLAUDE.md gains both new services. admin/ was never documented there at all:
the backend plan's wiring task covered compose and CI but not the file every
session actually loads. So this records admin's whole REST surface, its
404-not-403 rule, the three visual identities and, most importantly, that
adminsite/ and site/ share one token set with nothing enforcing the match --
the same hazard shape as sitesvc's mirrored slug rules.
Also notes that admin's REDIS_ADDR reaches admin only, because the base
compose hardcodes redis:6379 for server.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Removes vitest, React Testing Library, the config, the setup file and all
eleven test files, plus the test scripts and dev dependencies. Done at the
user's direction; it matches the rest of the repo, which has no automated
tests in any language.
All eleven were observed passing before removal, and their assertions are
kept in the plan as acceptance criteria to check by hand rather than deleted
outright -- they are the clearest statement of what each component has to do.
Consequence worth stating: Task 16's manual pass is now the only verification
that exists for spec 4. Four behaviours it must cover carefully, because each
is easy to break invisibly: 404-not-403 scoping, the expired card naming what
still works, relink disabling at zero, and the blob fallback when a download
fails.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>