Skip to content

v1.4.0

Latest

Choose a tag to compare

@jadenblack jadenblack released this 04 Nov 17:13
· 6 commits to main since this release
a43a5c0

[1.4.0] - 2026-11-04

The admin console, and relationship templates become products.

Admin

  • An audited operations console (epic #500): roles, an action log, template authoring,
    relationship repair, report regeneration, billing control, support inbox, broadcast and
    platform health. Every write passes one act() path that cannot mutate without a reason,
    and a PII read records itself.
  • product.admin is a template capability — a derived product inherits the console or
    turns it off, and answers 404 when off.

Relationship templates as products (#533)

  • Templates carry an owner and a visibility; public listing stays admin-curated.
  • Relationship lifecycle draft → pending → published → active → complete, with void/expired.
  • Per-relationship membership: 14-day trial from publish, one active trial per user,
    invite expires in 7 days, unlimited assessment rounds while paid, read-only for both sides
    when membership lapses.
  • Initiator CRUD: clone or start blank, edit Aspects, publish → trial or checkout,
    one-click re-publish.

Onboarding

  • First-run tour (driver.js, MIT) and a three-step counterparty wizard whose auth round-trip
    keeps the invite token and returns to the same step.

Brand and system

  • Icon set generated from the real mark, transparent ground (E38 guards it).
  • Palette: graphite #37474F action, cyan #08ADD5 accent (surface-only — contrast measured).
  • New checks: E39 fails a dashboard→marketing link without a new tab; E35 remains the
    ancestor rule.

Commits

  • feat(nav) — the rail is a role-constrained menu, and the admin console leads its own group (#542) (#552)
  • feat(templates) — a public Relationship Templates catalogue, and a home band that sells it (#544)
  • feat(flow) — counterparty onboarding — a three-step wizard, and a next on every login hop (#538)
  • feat(relationship) — #533 phase 3 — one trial, day-14 hard stop, read-only both sides, payment reactivates (#537)
  • feat(member) — #533 phase 2 — initiator CRUD, publish, one-click re-publish (#535)
  • feat(relationship) — template ownership, lifecycle, trial read and rounds (#533 phase 1) (#534)
  • feat(billing) — claim the host on a checkout and refuse another host's events (#532)
  • feat(admin) — broadcast to news signups (#507) (#531)
  • feat(admin) — #506 support inbox — triage, Resend replies with visible failure, bounce state, throttle visibility (#530)
  • feat(email) — #439b Resend inbound — signed webhook, idempotent email_event, bounce suppression (#528)
  • feat(admin) — #502b template versioning — template_version, relationships bound to a version, immutable publish (#524)
  • feat(admin) — #505 billing control — subscription state, test-mode banner, audited comps, server-side limits (#525)
  • feat(admin) — #504 report operations — regenerate, PII-gated read, JSON + PDF export (#523)
  • feat(admin) — #502a template authoring — a draft editor validated by zAssessment, saved through act() (#522)
  • feat(admin) — /admin/health — the platform-health screen, every number naming its source (#508) (#520)
  • feat(admin) — the five #503 actions, their floors, and a reason gate proven per operation (#517)
  • feat(admin) — #503 relationship operations (#516)
  • feat(admin) — /admin/audit — the filtered, read-only audit screen (#501b) (#515)
  • feat(admin) — the role ladder, admin_invite, admin_action and act() (#501) (#511)
  • feat(admin) — product.admin — the console's capability switch (#509) (#512)
  • feat(db-verify) — V21 — a seeded instance reads complete, or the run names it (#499)
  • feat(onboarding) — the first-run tour's shell — driver.js, six steps, skip a missing target (#455) (#496)
  • feat(onboarding) — the tour's "seen" mark is one column and one guarded route (#456) (#494)
  • feat(assessment) — the Steps render on the instance screen, and the v1 release rows retire (#478) (#493)
  • feat(demo) — move the worked example to /assessment/demo/[type] and delete the prototype group (#478) (#492)
  • feat(release) — --check-limits re-derives a Known limits block from the tree (#489)
  • feat(admin) — move the console to /admin/console, behind the allowlist (#478) (#486)
  • fix(brand) — the lockup is 2rem in every expanded-header viewport (#549 follow-up) (#553)
  • fix(help) — a sticky category rail beside the answers, and the person band beside the form (#549)
  • fix(brand) — the chrome draws the full lockup again, and the auth mark is a seal (#539) (#547)
  • fix(db) — serialise db:seed on the branch with an advisory lock (#529)
  • fix(demo) — record the #464 dataset in the demo expectations — 33 records, 172 items (#526)
  • fix(demo) — record the #464 template catalogue in demo:verify's counts (#527)
  • fix(admin) — #503 a revoke is terminal — a resend refuses a withdrawn invitation (#519)
  • fix(assessment) — the locked report's continue CTA opens the sheet, not the POST-only endpoint (#488)
  • feat(email) — the release note: one band, plain text first, sent once per tag (#548) (#551)
  • feat(dashboard) — support, help and the library live in the console (#542) (#546)
  • polish(v1.x) — the ten owner UI items — icon size, auth gap, Gap scale, tokens, footer band, one measure, rails (#539) (#543)
  • copy(home) — the register pass — title, practice band and boundary body (#545)
  • copy(home) — the hero pitches a leader's outcome, not a practitioner's practice (#541)
  • ux(rules) — a link out of the dashboard opens a new tab; a form surface carries no shadow (#540)
  • chore(ops) — version env-sync with the policy lists, --confirm-production and --diff (#536)
  • test(admin) — #503 the five repairs, their rung and the rollback (#521)
  • docs(brand) — the icon docs name the transparent ground, and parity only moves on a path (#514)
  • test(admin) — #503 the void and force-close screens, read as markup (#518)
  • brand — the icon set is the AS mark on transparency, and E38 fails when it is not (#510)
  • docs(release) — a seeded instance reading answering is stamped, never reseeded (#498)
  • docs(db-verify) — V11's comment says why a legitimate mark can still go stale (#497)
  • docs(release) — a V11 is repaired by clearing the mark, and a rule change is what creates one (#495)
  • refactor(v1) — delete the 95-row customer half of /v1, and prove /v1 404s (#478) (#491)
  • docs(registry) — the answer sheet's inbound paths name the report's CTA too (#490)
  • docs(release) — the v1.3.0 Known limit said the answer sheet had no link — it has one (#487)
  • fix(shell) — the surface registry calls create and answer live, because they are (#485)
  • docs(v1) — disposition all 118 /v1 items into docs/V1-RETIREMENT.md (#478) (#484)
  • docs(release) — a merge deploys production, measured during the v1.3.0 cut (#483)
  • Stripe is test mode only — no sk_live path exists in the code; checkout cannot charge
  • Chat has no persistence — /chat is a mocked surface with no tables behind it.
  • The Doubt gap kind is not computable — opinion keeps one value per kind, so the report
  • Neon-hosted auth mail is unverified — app mail sends through Resend and is proven;
  • Role-constrained menus and focused-flow chrome are not in this release (#542 phase 2).
  • An invite token is shown once (hashed at rest) — a lost link needs a re-publish.
  • No merge queue (#442); merges stay serial because main requires an up-to-date branch.

Known limits

  • Stripe is test mode only — no sk_live path exists in the code; checkout cannot charge
    a card, and the test-mode banner stays visible on purpose.
  • Chat has no persistence — /chat is a mocked surface with no tables behind it.
  • The Doubt gap kind is not computable — opinion keeps one value per kind, so the report
    states it rather than printing a number.
  • Neon-hosted auth mail is unverified — app mail sends through Resend and is proven;
    a Neon-side SMTP credential was rotated and its replacement is not yet confirmed by a reset.
  • Role-constrained menus and focused-flow chrome are not in this release (#542 phase 2).
  • An invite token is shown once (hashed at rest) — a lost link needs a re-publish.
  • No merge queue (#442); merges stay serial because main requires an up-to-date branch.