Version. 0.1
Date. 2026-08-03
Brief executed. inspection-briefs/loomworks-b41-verification-brief-v0_1.md
Charter. standing-notes/dunin7-standing-authorization-charter-v0_1. R-4 verification run.
Build-list item. B-41.
Status. Verification, executed. No repository change of any kind. No merge, no tag, no push to either target repository.
| Repository | Branch | SHA (this session, git rev-parse HEAD) | Tag | Tree state (git status --porcelain) |
|---|---|---|---|---|
| /Users/dunin7/loomworks-engine | main | ffc29afbe07bc917f3460f32491389db2fe7e713 | — | empty (clean) |
| /Users/dunin7/stele | main | 689de4192f68383edac2d0590ffa7ce195393e5c | v0.4.0 (git describe --tags --exact-match) | empty (clean) |
Both match the brief's header exactly, re-verified this session rather than inherited.
playground_dev and playground_test were never connected to. Every psql and every ALEMBIC_URL / DATABASE_URL / STELE_DATABASE_URL value used this session named one of three throwaway databases (below) or, for one \dt sanity check before any of them were created, a pre-existing unrelated database (playground_walkaudit, a leftover from a prior session, read-only \dt only, not written to, not otherwise used).
Three throwaway databases, created and dropped this session:
| Name | Owner | Purpose | Created via | Dropped |
|---|---|---|---|---|
| b41v1_engine | playground | Question one — engine-built schema | CREATE DATABASE ... OWNER playground as dunin7 (the playground role lacks CREATEDB) | Yes — DROP DATABASE b41v1_engine |
| b41v2_stele | playground | Question one — Stele-built schema alone | same | Yes — DROP DATABASE b41v2_stele |
| b41v3_sequence | playground | Question two — the full stand-up sequence | same | Yes — DROP DATABASE b41v3_sequence |
Confirmed dropped: psql -U dunin7 -h localhost -l | grep b41v returns nothing, run after all three DROP DATABASE commands.
.env was not edited. LOOMWORKS_SECRET_KEY was supplied inline (as an environment-variable prefix) on two commands only (noted at §3 and §4); every other command ran with no relevant variable set inline, relying on whatever .env-driven fallback exists in the code (see §4's environment-facts subsection — this fallback is itself a finding).
Yes. The stamp is safe. alembic stamp 0001_baseline followed by alembic upgrade head, run with Stele's own config against the database the engine's own chain built to head, both succeeded with no error, and principals.totp_last_step exists afterward with the correct type. This holds on two independently built throwaways (b41v1_engine, used for the isolated question-one run, and b41v3_sequence, used for the full question-two sequence) — the same result both times.
D-1 survives. The scoping note's Option B (run Stele's chain separately, as a documented step, stamping first) is verified to work against the shape the engine's chain actually produces, not merely plausible by reading Stele's README.
On a fresh throwaway (b41v1_engine), from empty:
$ ALEMBIC_URL="postgresql+asyncpg://playground@localhost/b41v1_engine" .venv/bin/alembic upgrade head
...
INFO [alembic.runtime.migration] Running upgrade 0033 -> 0034, Phase 15: Loomworks engagement induction.
Traceback (most recent call last):
...
File "/Users/dunin7/loomworks-engine/migrations/versions/0034_phase_15_loomworks_engagement_induction.py", line 277, in upgrade
raise RuntimeError(
RuntimeError: administrative engagement not present — required for seed_requirements_engagement_version_at_induction
Confirms the findings' prediction exactly: the chain stops at 0034, with the exact error text the findings quoted.
A finding the brief did not anticipate: this single alembic upgrade head invocation rolled back everything, not just 0034.
$ psql -U playground -h localhost -d b41v1_engine -c "SELECT version_num FROM alembic_version;"
ERROR: relation "alembic_version" does not exist
$ psql -U playground -h localhost -d b41v1_engine -c "\dt"
Did not find any relations.
After the failed upgrade head, the database had zero tables — not 33 migrations' worth of committed schema with 0034 merely absent. Alembic wraps one upgrade invocation spanning multiple revisions in a single transaction (Postgres supports transactional DDL, and nothing in either env.py disables this); a failure anywhere in that invocation rolls back every revision the invocation attempted, not only the one that raised. This is recorded here because it directly shapes the sequence at §4 — targeting head from empty is not a safe way to "get as far as the chain goes," because a failure partway looks identical, at the database level, to nothing having run at all. The database has to be walked to an explicit intermediate revision (0033) in its own invocation for that progress to be committed:
$ ALEMBIC_URL="postgresql+asyncpg://playground@localhost/b41v1_engine" .venv/bin/alembic upgrade 0033
INFO [alembic.runtime.migration] Running upgrade -> 0001, ...
...
INFO [alembic.runtime.migration] Running upgrade 0032 -> 0033, Phase 14: add first_login_at to persons.
$ psql -U playground -h localhost -d b41v1_engine -c "SELECT version_num FROM alembic_version;"
version_num
-------------
0033
$ psql -U playground -h localhost -d b41v1_engine -c "\dt" | wc -l
28
This succeeded and committed 27 tables plus alembic_version. Re-running upgrade head from this already-stamped 0033 state failed at 0034 again with the identical error, but this time left the database at 0033 (the earlier 27 tables intact, alembic_version still 0033) — because this second invocation's transaction only ever touched 0034, which is what failed and rolled back. The lesson: a failure's blast radius is the invocation, not the revision — split the walk into invocations at the points you need to survive a failure.
To read principals as the engine's chain actually produces it (created at 0085, downstream of the 0034 break), the chain had to be carried past 0034 — the same minimal bootstrap the brief's §4 step 2 names, invoked here for question one's purposes, not as an endorsement of it as the final entry point (that remains D-2's open question):
$ DATABASE_URL="postgresql+asyncpg://playground@localhost/b41v1_engine" \
LOOMWORKS_SECRET_KEY="kraIDIQCkc-UvDG_s3iAaWpArWNR4fb8_uVZKsWm7C0=" \
.venv/bin/python3 -c "
import asyncio
from loomworks.config import settings
from loomworks.db import make_engine, make_session_factory
from loomworks.engagement.bootstrap import ensure_administrative_engagement, ensure_seed_requirements, ensure_e2e_test_engagement
from loomworks.credit.bootstrap import ensure_credit_engagements
async def main():
engine = make_engine(settings.database_url)
factory = make_session_factory(engine)
async with factory() as session:
async with session.begin():
await ensure_administrative_engagement(session)
await ensure_seed_requirements(session)
await ensure_e2e_test_engagement(session)
await ensure_credit_engagements(session)
await engine.dispose()
print('bootstrap OK')
asyncio.run(main())
"
bootstrap OK
$ ALEMBIC_URL="postgresql+asyncpg://playground@localhost/b41v1_engine" .venv/bin/alembic upgrade head
... (runs 0034 through 0102 cleanly) ...
$ psql -U playground -h localhost -d b41v1_engine -c "SELECT version_num FROM alembic_version;"
version_num
-------------
0102
principals at engine head (\d principals, b41v1_engine):
Table "public.principals"
Column | Type | Collation | Nullable | Default
------------------------+--------------------------+-----------+----------+---------
id | uuid | | not null |
display_name | text | | not null |
totp_secret | text | | |
first_login_at | timestamp with time zone | | |
last_presence_proof_at | timestamp with time zone | | |
created_at | timestamp with time zone | | not null | now()
updated_at | timestamp with time zone | | not null | now()
Indexes:
"principals_pkey" PRIMARY KEY, btree (id)
(plus 15 FK constraints from other tables referencing it — companion_notifications, conversation_turns, engagement_tags, engagements, credit.credit_grant, host_account ×2, memberships, organization_memberships, person_settings, recovery_codes, saved_filters, uploaded_files, webauthn_credentials, workspaces)
webauthn_credentials (b41v1_engine):
Table "public.webauthn_credentials"
Column | Type | Collation | Nullable | Default
---------------+--------------------------+-----------+----------+-------------------
id | uuid | | not null | gen_random_uuid()
person_id | uuid | | not null |
credential_id | bytea | | not null |
public_key | bytea | | not null |
sign_count | integer | | not null | 0
transports | jsonb | | |
display_name | text | | |
created_at | timestamp with time zone | | not null | now()
Indexes:
"webauthn_credentials_pkey" PRIMARY KEY, btree (id)
"idx_webauthn_credentials_person" btree (person_id)
"uq_webauthn_credentials_credential_id" UNIQUE CONSTRAINT, btree (credential_id)
Foreign-key constraints:
"webauthn_credentials_person_id_fkey" FOREIGN KEY (person_id) REFERENCES principals(id)
recovery_codes (b41v1_engine):
Table "public.recovery_codes"
Column | Type | Collation | Nullable | Default
----------------+--------------------------+-----------+----------+-------------------
id | uuid | | not null | gen_random_uuid()
person_id | uuid | | not null |
code_hash | text | | not null |
used_at | timestamp with time zone | | |
created_at | timestamp with time zone | | not null | now()
invalidated_at | timestamp with time zone | | |
Indexes:
"recovery_codes_pkey" PRIMARY KEY, btree (id)
"idx_recovery_codes_person" btree (person_id)
Foreign-key constraints:
"recovery_codes_person_id_fkey" FOREIGN KEY (person_id) REFERENCES principals(id)
On b41v2_stele, nothing else present:
$ STELE_DATABASE_URL="postgresql+asyncpg://playground@localhost/b41v2_stele" .venv/bin/alembic upgrade head
INFO [alembic.runtime.migration] Running upgrade -> 0001_baseline, baseline — Stele 3-table schema (principals, webauthn_credentials, recovery_codes)
INFO [alembic.runtime.migration] Running upgrade 0001_baseline -> 0002_totp_last_step, ...
principals (b41v2_stele):
Table "public.principals"
Column | Type | Collation | Nullable | Default
------------------------+--------------------------+-----------+----------+---------
id | uuid | | not null |
display_name | text | | not null |
totp_secret | text | | |
first_login_at | timestamp with time zone | | |
last_presence_proof_at | timestamp with time zone | | |
created_at | timestamp with time zone | | not null | now()
updated_at | timestamp with time zone | | not null | now()
totp_last_step | integer | | |
Indexes:
"principals_pkey" PRIMARY KEY, btree (id)
(plus 2 FK constraints — recovery_codes, webauthn_credentials — the only two other tables that exist in this throwaway; this is a consequence of b41v2_stele containing only Stele's three tables, not a schema difference in principals itself.)
webauthn_credentials and recovery_codes (b41v2_stele) — column-for-column, type-for-type, default-for-default, index-for-index identical to §2.2's engine-built versions above. Diffed by direct comparison of both \d outputs; no difference found in either table.
Exactly one difference across all three tables: principals.totp_last_step, present in Stele's build (integer, nullable, no default) and absent from the engine's build. No difference in any column's type, nullability, default, primary key, index name, or foreign-key constraint was found anywhere else — including in webauthn_credentials and recovery_codes, which the findings did not single out as at-risk but which this session diffed in full per the brief's §3.4 instruction ("report every difference, not only the ones that would break a stamp").
Confirms the findings' prediction exactly.
Against b41v1_engine at engine head (0102, three tables built per §2.2):
$ STELE_DATABASE_URL="postgresql+asyncpg://playground@localhost/b41v1_engine" .venv/bin/alembic stamp 0001_baseline
INFO [alembic.runtime.migration] Running stamp_revision -> 0001_baseline
$ psql -U playground -h localhost -d b41v1_engine -c "SELECT * FROM stele_alembic_version;"
version_num
---------------
0001_baseline
Exit code 0. No error, no warning, no constraint conflict — stamp writes only to stele_alembic_version; it does not touch principals, webauthn_credentials, or recovery_codes themselves, so there was nothing for it to fail against regardless of the shapes matching.
$ STELE_DATABASE_URL="postgresql+asyncpg://playground@localhost/b41v1_engine" .venv/bin/alembic upgrade head
INFO [alembic.runtime.migration] Running upgrade 0001_baseline -> 0002_totp_last_step, totp last step — persist last-accepted TOTP time-step per principal (TS-11 replay protection)
Exit code 0. This is the step that actually exercises whether the shapes match — 0002_totp_last_step runs op.add_column("principals", ...) against a principals table it did not create, and if the engine-built table disagreed with what Stele's model expects in a way Postgres would reject (a conflicting column, an incompatible type on a column it touches), this is where it would surface. It did not.
$ psql -U playground -h localhost -d b41v1_engine -c "\d principals"
...
totp_last_step | integer | | |
...
totp_last_step exists, type integer, nullable, matching §2.3's Stele-alone build exactly.
The verdict this question returns: the stamp is safe. Verified twice — once in isolation (this section) and once as part of the full sequence (§3) — with the identical result both times.
On a third, separate throwaway, b41v3_sequence, from empty.
0033
$ ALEMBIC_URL="postgresql+asyncpg://playground@localhost/b41v3_sequence" .venv/bin/alembic upgrade 0033
INFO [alembic.runtime.migration] Running upgrade -> 0001, ...
...
INFO [alembic.runtime.migration] Running upgrade 0032 -> 0033, Phase 14: add first_login_at to persons.
$ psql -U playground -h localhost -d b41v3_sequence -c "SELECT version_num FROM alembic_version;"
version_num
-------------
0033
Succeeded, no error.
No standalone entry point exists for this — confirmed again this session (per findings §2.1, the only invocation site is _lifespan in app.py). The minimal means used: a Python one-liner that imports the same four ensure_* functions _lifespan calls, in the same order, inside the same session.begin() transactional pattern, and runs them directly against the throwaway's DATABASE_URL:
$ DATABASE_URL="postgresql+asyncpg://playground@localhost/b41v3_sequence" .venv/bin/python3 -c "
import asyncio
from loomworks.config import settings
from loomworks.db import make_engine, make_session_factory
from loomworks.engagement.bootstrap import ensure_administrative_engagement, ensure_seed_requirements, ensure_e2e_test_engagement
from loomworks.credit.bootstrap import ensure_credit_engagements
async def main():
engine = make_engine(settings.database_url)
factory = make_session_factory(engine)
async with factory() as session:
async with session.begin():
await ensure_administrative_engagement(session)
await ensure_seed_requirements(session)
await ensure_e2e_test_engagement(session)
await ensure_credit_engagements(session)
await engine.dispose()
print('bootstrap OK')
asyncio.run(main())
"
bootstrap OK
Notably, this succeeded without LOOMWORKS_SECRET_KEY set inline — the four ensure_* functions called here evidently do not need it (see §4's environment-facts subsection for where the key actually is needed).
This is the shape D-2's standalone entry point has to provide: the same four calls, the same order, the same transactional wrapping, callable without booting _lifespan.
$ ALEMBIC_URL="postgresql+asyncpg://playground@localhost/b41v3_sequence" .venv/bin/alembic upgrade head
INFO [alembic.runtime.migration] Running upgrade 0033 -> 0034, ...
... (runs cleanly through 0102, including 0062/0063/0064's LOOMWORKS_SECRET_KEY-gated encryption steps — no error) ...
$ psql -U playground -h localhost -d b41v3_sequence -c "SELECT version_num FROM alembic_version;"
version_num
-------------
0102
Succeeded, no error. Reached the repository's declared head.
$ STELE_DATABASE_URL="postgresql+asyncpg://playground@localhost/b41v3_sequence" .venv/bin/alembic stamp 0001_baseline
INFO [alembic.runtime.migration] Running stamp_revision -> 0001_baseline
$ STELE_DATABASE_URL="postgresql+asyncpg://playground@localhost/b41v3_sequence" .venv/bin/alembic upgrade head
INFO [alembic.runtime.migration] Running upgrade 0001_baseline -> 0002_totp_last_step, ...
$ psql -U playground -h localhost -d b41v3_sequence -c "SELECT version_num FROM alembic_version;"
version_num
-------------
0102
$ psql -U playground -h localhost -d b41v3_sequence -c "SELECT version_num FROM stele_alembic_version;"
version_num
---------------------
0002_totp_last_step
Both succeeded, no error. Same result as the isolated run at §2.5.
Test one — the engine's own test-suite precondition, replicated directly:
$ psql -U playground -h localhost -d b41v3_sequence -c "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'public' AND table_name IN ('engagements', 'memory_events', 'current_memory_objects');"
count
-------
3
Matches tests/conftest.py's engine fixture precondition exactly (it wants count == 3). This was run as a direct SQL query against b41v3_sequence rather than by pointing database_url_test at the throwaway, to avoid any risk of the test harness's other fixtures touching playground_test — the fences protect playground_test, and the fixture's own check is a single, reproducible SQL statement, so replicating it directly answers the same question without that risk.
Test two — can the application boot against it:
$ DATABASE_URL="postgresql+asyncpg://playground@localhost/b41v3_sequence" \
LOOMWORKS_SECRET_KEY="kraIDIQCkc-UvDG_s3iAaWpArWNR4fb8_uVZKsWm7C0=" \
.venv/bin/python3 -c "
import asyncio
from loomworks.api.app import create_app
from httpx import AsyncClient, ASGITransport
async def main():
app = create_app()
async with app.router.lifespan_context(app):
transport = ASGITransport(app=app)
async with AsyncClient(transport=transport, base_url='http://test') as client:
r = await client.get('/healthz')
print('status', r.status_code, r.text)
asyncio.run(main())
"
status 200 {"version":"0.1.0","database_reachable":true,"administrative_engagement_present":true}
The app booted (ran _lifespan's startup, including the same idempotent ensure_* calls — a no-op since Step 2 already planted the rows) and /healthz reported the database reachable and the administrative engagement present.
Test three — does the alembic head match the repository's declared head:
$ .venv/bin/alembic heads # loomworks-engine
0102 (head)
$ .venv/bin/alembic heads # stele
0002_totp_last_step (head)
Both match what b41v3_sequence's two version tables recorded at §3.4 (0102, 0002_totp_last_step) exactly.
All three tests pass. The sequence produces a working database.
# 1. Engine chain to the last revision before the break.
ALEMBIC_URL="postgresql+asyncpg://<user>@<host>/<db>" \
uv run --project /Users/dunin7/loomworks-engine alembic -c /Users/dunin7/loomworks-engine/alembic.ini upgrade 0033
# 2. The bootstrap — no standalone entry point exists yet (this is D-2's open item).
# Minimal means used this session: a one-liner calling the same four ensure_*
# functions _lifespan calls, in the same order, inside one transaction.
DATABASE_URL="postgresql+asyncpg://<user>@<host>/<db>" \
uv run --project /Users/dunin7/loomworks-engine python3 -c "<see §3.2>"
# 3. Engine chain to head.
ALEMBIC_URL="postgresql+asyncpg://<user>@<host>/<db>" \
uv run --project /Users/dunin7/loomworks-engine alembic -c /Users/dunin7/loomworks-engine/alembic.ini upgrade head
# 4. Stele's own chain, stamped then upgraded, against the same database,
# using Stele's own alembic.ini (not the engine's).
STELE_DATABASE_URL="postgresql+asyncpg://<user>@<host>/<db>" \
uv run --project /Users/dunin7/stele alembic stamp 0001_baseline
STELE_DATABASE_URL="postgresql+asyncpg://<user>@<host>/<db>" \
uv run --project /Users/dunin7/stele alembic upgrade head
(This session invoked each repo's .venv/bin/alembic / .venv/bin/python3 directly rather than through uv run, since both venvs were already current; uv run --project <dir> ... is the equivalent a written procedure should name, so a reader without an already-built venv still gets a correct command.)
Four commands, not three — the scoping note's §2 estimate ("a fresh stand-up becomes three commands rather than one") undercounts by one: D-1's stamp and upgrade are two separate commands (stamp 0001_baseline, then upgrade head), not one. Five commands total, counting both the engine's split (upgrade 0033, upgrade head) and Stele's split (stamp, upgrade head), plus the bootstrap — six, if the bootstrap's one-liner is counted as a single command, which is how it was run this session.
alembic upgrade head from empty looks safe to retry and isn't informative when it fails. Per §2.1, a failed multi-revision invocation rolls back everything it touched, not just the failing revision. A reader who runs upgrade head from empty, sees it fail at 0034, and then inspects the database will find zero tables — indistinguishable, at a glance, from the command having done nothing at all. The ordering that looks optional and is not: split the walk at 0033 in its own invocation before doing anything else, or the 33 migrations' worth of prior progress evaporates every time.bootstrap.py's docstrings) — a second invocation returns cleanly having changed nothing, which is correct but easy to mistake for "it worked" in the sense of "it just created the rows," when actually it found them already present. Not tested by re-running it a second time this session (out of scope — the sequence only needed it once per throwaway), but named here because the idempotency claim is what makes Step 2 safe to run speculatively, and a reader relying on that claim should know it comes from the function's own docstring, not from this session having exercised the second-call path.LOOMWORKS_SECRET_KEY-gated migrations (0062, 0063, 0064). This session never saw them fail — see §4.3 — but the findings' own reading of 0062's comment (RuntimeError text ending "...and re-run the upgrade") already names the recovery path, and this session's read of the same helper (§4.3) shows why it didn't fail here: a same-process fallback to .env, not a property of the migration being safe to skip.alembic stamp 0001_baseline succeeds unconditionally (§2.5 — it only writes a row to stele_alembic_version; it never inspects principals). Running it against a database where the engine's chain has not yet built principals (e.g., stamping before Step 1/3 instead of after) would leave stele_alembic_version claiming 0001_baseline is applied when no table it describes actually exists — a silent, self-consistent-looking lie that only Step 4's second command (upgrade head, which does touch principals) would eventually expose, and only if something about 0002's add_column fails against a table that was never created. Ordering matters here in a way the stamp command itself gives no feedback about.alembic.ini and Stele's alembic.ini are separate files with separate script_locations; cd-ing into the wrong repository (or omitting -c <path> / not being in the right working directory) runs the wrong chain against the same -URL variable's target, silently, since both accept a database URL and neither validates that the URL "belongs" to it..env's own DATABASE_URL for all of them: ALEMBIC_URL (engine's Alembic; falls back to settings.database_url / .env's DATABASE_URL if unset), DATABASE_URL (the bootstrap one-liner and app boot, via loomworks.config.settings), and STELE_DATABASE_URL (Stele's Alembic; no fallback — raises immediately if unset, per stele/src/stele/migrations/env.py:35-38, confirmed by direct read this session). A reader who sets only one, assuming it wires the whole sequence, will find some steps silently pointed at .env's playground_dev instead of the throwaway.No contradiction of the findings or the scoping note was produced by this run. Every prediction named in either grounding document as an expectation to confirm or contradict was confirmed:
0034 with the exact quoted error (findings §3.1; confirmed §2.1).principals.totp_last_step is the sole diff between the engine-built and Stele-built shapes (findings §3.3; confirmed §2.4).LOOMWORKS_SECRET_KEY is named at 0062/0063/0064 (findings §3.2; confirmed present in the code path — but see §4.3 below for what this run adds that neither grounding document stated).
One thing this run adds, not a contradiction but a gap in both grounding documents: neither named the transaction-rollback behavior at §2.1, nor the .env fallback inside _fernet_encrypt at §4.3. Both were unread until this session ran the chain; both are now recorded here rather than estimated.
A correction to this session's own initial assumption, caught before it reached the deliverable: the brief's §3.1 instruction ("build the engine's schema as far as it goes... record where it stops") was initially read as sufficient on its own for §3.2's table capture. It is not — principals does not exist until 0085, past the 0034 break, so §3.2's instruction to "read from the live throwaway" required carrying the same database past 0034 using the bootstrap, which is not mentioned until the brief's §4. This is recorded as a gap in the brief's own sequencing between §3 and §4, not as an error in either grounding document — the brief authorized "whatever minimal means works" for the bootstrap at §4 step 2, and this run applied that same authorization one section earlier than the brief's prose introduces it, because question one's own instructions required it.
LOOMWORKS_SECRET_KEY was needed, and at which revisions. The findings named 0062, 0063, 0064 as gated on it. This session ran the full chain to head twice (once on b41v1_engine, once on b41v3_sequence) with LOOMWORKS_SECRET_KEY not set inline for the alembic upgrade head command either time, and both runs passed 0062–0064 without error. Reading _fernet_encrypt in all three files (0062:79-104, 0063:60-, 0064:71-) explains why: each falls back to os.environ.get("LOOMWORKS_SECRET_KEY", ""), and if that is empty, falls back a second time to loomworks.config.settings.loomworks_secret_key — which reads .env, and this project's .env already carries the key (confirmed present, not echoed here per the memory-system's own handling rule). So the key was needed, and was supplied — by .env, silently, not by anything this session set. A database stood up in an environment without that .env entry would hit the RuntimeError these three migrations name, and per the brief's own reading of the comment, the fix is documented in the error text itself (set the key, re-run).env.py files this session: ALEMBIC_URL (engine Alembic, falls back to .env's DATABASE_URL), DATABASE_URL (app boot / the bootstrap one-liner, via settings.database_url, no Alembic-specific override), STELE_DATABASE_URL (Stele Alembic, no fallback, hard-raises if unset). Named as a person-or-agent trap at §4.2.playground role cannot CREATE DATABASE (confirmed: CREATE DATABASE b41v1_engine OWNER playground; as playground returned ERROR: permission denied to create database; the same command as dunin7 succeeded). Every throwaway this session had to be created as a role with CREATEDB and owner-assigned to playground afterward — not previously written down anywhere in either repository or the record.LOOMWORKS_SECRET_KEY's absence actually triggers the documented RuntimeError, by unsetting it from .env (or pointing at an environment where it was never set) and re-running 0062. Not attempted — the fences say .env stays untouched, and no throwaway environment without an .env-level fallback was set up, since the sequence's own real-world use will have a real .env in essentially every case this session could construct.playground_dev's actual schema matches what the chain produces; which route historically created playground_dev's administrative-engagement row; whether any environment other than playground_dev has run the chain from empty. None of these needed a live production connection this session did not have, and the fences forbid opening one.DUNIN7 — Done In Seven LLC — Miami, Florida Loomworks — B-41 verification findings — v0.1 — 2026-08-03 The stamp is safe, the sequence works, and the two facts neither grounding document could state without running it are now recorded.