Fourth section of #23. db-dsn now names the console's runtime user, and
the new db-migrate-dsn (or db-migrate-dsn-file) names the user that runs
migrations. start opens both, migrates on the migration connection,
grants console_runtime to the runtime user there (WITH INHERIT TRUE, the
name quoted by the database), closes it, and serves on the runtime pool
alone. With db-migrate-dsn left out, start runs no migration and refuses
when the schema is behind its code, which is how a host runs migrations
as a separate step; migrate up, down and status use the migration string
and refuse without it, with no fallback to db-dsn.
Both pools are opened from one pgx.ParseConfig: the migration pool's
search_path is public and both pools' role is none, set in the startup
parameters after every key of either name is removed case-insensitively,
so neither a setting the database or role carries nor a key the string
repeats in another case moves a session off its login or its path.
PendingMigrations reads each stream's ledger by qualified name inside a
transaction pinned to search_path pg_catalog, pg_temp.
The test stack runs on two users: postgres-seed creates
member_console_runtime in new and existing volumes, bootstrap-stack.sh
writes MC_DB_DSN as that user and MC_DB_MIGRATE_DSN as member_console,
and the four scripts refuse a .env without the migration string, with
the command that regenerates it. Scripts and fixtures that need a
superuser on the application database (the reset, the screens'
timestamp pinning) use the migration string.
This worktree's stack was regenerated with that command and the console
booted as member_console_runtime: its sessions were the runtime user's
only, no migration-user session stayed open, and the runtime user could
not insert into core.pool_provisions.
Full suite on reset databases: 4277 pass, 15 skip, none failed. The
walkthroughs' names, results and skip messages match the previous
section's run. make screens lists three changed screens, all data:
regenerated ids on operator-person-detail and
operator-billing-invoice-detail (the demo snapshot was rebuilt) and a
domain's age on operator-domains (294d to 295d); the baseline was not
accepted. make lint passes.
Deliberate breaks, scripts/mutation-check -side new, all CAUGHT (36):
dbRuntime runs the migrations on the runtime pool
dbRuntime skips the boot grant
dbRuntime leaves the migration pool open
dbRuntime skips the pending check when db-migrate-dsn is unset
dbRuntime migrates on db-dsn when db-migrate-dsn is unset
GrantRuntimeRole without WITH INHERIT TRUE
GrantRuntimeRole with %s in place of %I
PendingMigrations takes a missing ledger as current
PendingMigrations resolves the ledger without the public. qualifier
the migration pool opened without search_path=public
the migration pool opened without role=none
the runtime pool opened without role=none
ConnectMigration keeps the search_path and role the string carries
dbMigration falls back to db-dsn
ValidateStart accepts a malformed db-migrate-dsn
db-migrate-dsn-file is not a database secret pair
db-migrate-dsn-file is not a database secret pair (the migrate commands read db-dsn-file only)
the bootstrap guard removed
reset-test-db.sh guard removed
seed-demo.sh guard removed
reset-app-db.sh guard after its first psql
startup parameters match their keys case-sensitively
the migration pool opened without role=none (keys and options in the string)
the runtime pool opened without role=none (keys and options in the string)
the runtime pool replaces the search_path the string carries
the string's spaces are written as plus signs
ValidateStart reads db-migrate-dsn as set whatever it holds
PendingMigrations lists only the versions the ledger shows when it is missing
migrationDSN keeps whitespace
migrate up accepts a whitespace-only db-migrate-dsn
runtimeDSN accepts a whitespace-only db-dsn
openDB runs the migrating boot for an unknown mode
bootstrap-stack.sh trusts the exported MC_DB_MIGRATE_DSN
reset-test-db.sh trusts the exported MC_DB_MIGRATE_DSN
reset-app-db.sh trusts the exported MC_DB_MIGRATE_DSN
seed-demo.sh trusts the exported MC_DB_MIGRATE_DSN
The farm is named under localtest.me, a public domain, because FedWiki's
sign-in shares one session cookie across its sites and browsers do not
scope a cookie to .localhost. A resolver that drops public names pointing
at loopback (a router's DNS-rebind protection, some office resolvers and
VPNs, or no network) made the app's farm call fail with "no such host",
the sites walkthrough time out in its first phase, and the reachability
guard report the farm as not composed (#236).
The guard now looks the endpoint's host up first and fails the test with
the host, the reason, and the two /etc/hosts lines that fix it. A name
defined to point at this machine must resolve to loopback; any other host
may resolve anywhere. bootstrap-stack.sh runs the same check on the
farm's admin name when the fedwiki profile is on and warns on stderr
without failing. test/AGENTS.md says which names must resolve here and
why.
bootstrap-stack.sh took its first argument as the stack's slug,
whatever it was, so `./bootstrap-stack.sh --help` would have written
--help into test/.env as COMPOSE_PROJECT_NAME. The slug becomes the
Compose project name, so the script now holds an explicit slug to
Compose's project-name rule (lowercase letters, digits, '-' and '_',
starting with a letter or a digit). For any other argument, or for
more than one, it prints its usage line on stderr and exits 2 before
its first git call. No argument, and a slug that follows the rule,
behave as before.
TestScriptsRefuseUnknownArguments gains a bootstrap-stack.sh group of
8 leaf subtests: 2 accepted (no argument, a slug) that stop at the git
stub, and 6 refused (--help, -h, an empty argument, an uppercase slug,
a slug led by an underscore, two arguments). At the parent the same
test file fails the 6 refusal rows, each running on to the git stub
and exiting 1 where 2 and the usage line are wanted, and passes the 2
accepted rows. At the commit all 23 leaf subtests of the test pass.
Not probed: the real script was not run, with or without an argument,
because it writes test/.env for the worktree it runs in.
- Replace gorilla/csrf with net/http CrossOriginProtection
- Require valkey-password and add TLS options for session store
- End session at /logout and revoke refresh tokens
- Re-derive identity and roles from provider every five minutes
- Process each Stripe webhook event in its own Temporal workflow
- Give each outbox entry its own workflow with Temporal retries
- Guard against stale Stripe events with provider timestamps
- Derive transport security from base-url scheme
- Add deployment-name branding to titles, mastheads, and OG tags
- Share one grant delivery-state query with lineage across grants
surfaces
- Show pool status/usage, org owners, and config readiness
- Make billing views projection-aware with recency and sync vocabulary
- Guard FedWiki creation without domains and render route-aware 404s
Guard cluster-global CREATE ROLE in all five migration streams with
pg_roles checks so multiple databases can migrate in one cluster, and
tolerate still-referenced roles on Down.
Add test/reset-test-db.sh to drop and recreate member_console_test and
member_console_e2e per run, emit their DSNs from bootstrap, and add a
make test target that resets then runs the suite serialized; parallel
unit packages sharing one database still interfered even after the e2e
split.
Fix customdomain_db_test.go, stale since 0affda7 and previously passing
only through pollution. Bootstrap and the Makefile carry small forward
references to the compose-profile knob introduced next.
Archives the test-db-isolation change.
Deliver forum posting entitlements through managed group membership with
identity linkage, periodic reconciliation, webhook handling, and an
operator mapping surface.
Include fake and live test environments, setup documentation,
migrations,
and end-to-end coverage.
Gate Stripe readiness on real credentials, surface dead-lettered syncs
as
failed with retry, and add header-safe toast JSON encoding.
Switch the test Keycloak realm references to `test` and document the
OpenSpec change.
Seed Keycloak into a dedicated wikicafe app realm and repoint the
test OIDC, Temporal, and FedWiki wiring to it.
Label test credentials as throwaway, remove the unused realm export from
tracking, and have init write the embedded starter config.
farm
Replace wiki-security-passportjs with wiki-security-social across
FedWiki configuration, docs, and workflows, and introduce a Caddy TLS
proxy so browser login works over HTTPS with Secure cookies. Update
Keycloak OIDC discovery URLs, OAuth2 identity mapping, and test-stack
HTTPS handling while preserving the existing owner.json and API
contracts.
Add a fedwiki-render compose service and render.sh to resolve real
Keycloak user UUIDs and render .tpl templates into testdata on compose
up.
Convert hardcoded FedWiki testdata into templates, add seed-stack.sh
helper,
and update compose/env and .gitignore to run seeding before starting
fedwiki.
Use the unified ./cmd entrypoint in test docs and bootstrap scripts
instead of ./cmd/member-console. Add derive_slug to pick a more
informative SLUG for worktrees (prefer parent dir or branch when the
basename is "member-console"). Improve teardown to remove root-owned
test files via a short-lived docker container fallback.