getAppProfile indexed the profile record directly, so on the one route
without a slug enum -- GET /v1/apps/:appSlug -- every Object.prototype
key answered 200 with an empty profile body. Object.hasOwn guards it.
brandCaller minted a mutable object, so a legitimately held caller for
one app could be re-slugged into another and keep its brand. Frozen at
mint. Soul's prototype-chain forgery now has to be built with
defineProperty, because shadowing a non-writable inherited property by
assignment throws first -- that construction is dead on arrival.
The OAuth callback's 502 echoed the store's own error text as `detail`,
which on Postgres would hand the caller a unique-constraint name. Fixed
string now; the full text stays in the audit event.
Four of Soul's tests asserted these holes and are flipped to assert the
closures, not deleted.
tsc --noEmit -p tsconfig.json -> exit 0
vitest run -> Tests 147 passed | 2 skipped (149)
tests/odin-publication.test.ts still fails on Cannot find module
'cultcache-ts', red on origin/main too.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>