Closes audit-1-5 section 4: six call sites in svrs/auth/adapters/db.ts
repeated the same `as unknown as Readonly<Record<string, unknown>>`
double cast when forwarding typed inputs to the generic
`AuthRepository.findOne` / `findMany` signature. Centralized the cast
in a single private `whereOf<T>(input)` helper so future tightening
(e.g. adding a brand or replacing the repository where-clause shape)
only changes one line.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Closes audit-1-5 section 5 drift in arts/buss/README.md:
- Sess publisher example now uses `publishSessLifecycleEvent` (the
fanout publisher) and `onSessChanged`; the obsolete
`publishSessIdentityChanged` / `onSessIdentityChanged` example is
removed.
- Session-translator example uses `resolveAppIdentityCause(payload.event)`
to map each lifecycle event to its corresponding cause, instead of
hardcoding `APP_USER_IDENTITY_CAUSE_SESSION_ADOPTED` for every event.
- App-event constants and string values updated to the real `AAPP_*`
prefix: `APP_EVENT_*` -> `AAPP_EVENT_*`, `'app.*'` -> `'aapp.*'`.
- `AAPP_EVENT_RUNTIMES` example aligned with the actual shape (uses
the `AAPP_EVENT_RUNTIME_BOTH/CLIENT` constants and proper type
alias instead of bare string literals).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Closes audit-1-5 section 3.3 and 3.5:
- arts/conn and arts/fend `dispose()` now guard against double-call.
- arts/lang circular-reference path throws `LangCircularReferenceError`
(new typed error in libs/lang) instead of plain `Error`.
- libs/perm filter-without-actor path throws the existing
`PermissionRuntimeError` instead of plain `Error`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Continues phase 4 — sweeps the next batch of modules onto the
canonical CodeError base. Same mechanical pattern as sium:
- Add `<MOD>_ERR` module seed and `<MOD>_ERR_*` codes via
`moduleSeed` + `errCode`.
- Convert error classes to `extends CodeError`. Drop the hardcoded
`this.name = 'XxxError'` literals — `name` derives from the code.
- Drop the `<MOD>_ERROR_NAME_*` constants that only existed to feed
those literals.
- Type guards keep using `instanceof Class` (works through the
CodeError prototype chain).
- Subclass-specific fields (envelope, failures, depth, type, key,
channel, connection, decision, invariant, etc.) preserved.
Modules migrated this commit:
- libs/buss (4 classes): BusDisposedError, BusAggregateListenerError,
BusReentrancyLimitError, BusInvalidPayloadError
- arts/timr (5 classes): TimrDisposedError, TimrInvalidKeyError,
TimrDuplicateKeyError, TimrInvalidDelayError, TimrInactiveTimerError
(codes live in libs/timers; classes stay in arts/timr)
- arts/conn (8 classes): ConnDisposedError, ConnConnectionAlreadyExistsError,
ConnConnectionNotFoundError, ConnInvalidConnectionNameError,
ConnInvalidFrameError, ConnChannelAlreadyExistsError,
ConnChannelNotFoundError, ConnWebSocketUnavailableError. Adds the
two missing guards flagged by audit-1-5 section 3.2
(isConnChannelAlreadyExistsError, isConnChannelNotFoundError).
- arts/sess (3 classes): SessDisposedError, SessAlreadyCreatedError,
SessInvalidSessionError. Sess test updated to assert against the
new code-based name.
- libs/perm + arts/perm + svrs/perm (3+4+2 classes): PermissionDeniedError,
PermissionSchemaError, PermissionRuntimeError, PermInvalidEndpointError,
PermNoContextError, PermRemoteRequestError, PermDisposedError (×2),
PermInvalidBodyError. Codes live in libs/perm; arts and svrs reach
into them.
- libs/cach + arts/cach + svrs/cach (3+1+1 classes): CacheKeyError,
CacheScopeError, CachePolicyError, CachActiveEntryDisposedError,
CachDisposedError. Codes consolidated in libs/cach.
Plus audit-1-5 section 3.2 cleanup outside the migration:
- libs/auth/errors.ts: adds the 10 missing type guards
(isAuthAccountNotLinkedError, isAuthSessionRevokedError,
isAuthAssuranceRequiredError, isAuthRateLimitedError,
isAuthTenantBoundaryError, isAuthOAuthStateInvalidError,
isAuthOAuthProviderError, isAuthOtpInvalidError,
isAuthMfaRequiredError, isAuthWebAuthnError). Auth's own
`code`/`messageKey` shape is preserved for now — full migration
to CodeError needs more thought because of the existing
AUTH_ERROR_CODES/AUTH_SAFE_MESSAGES dual structure.
Verification: svelte-check 1403 files / 0 errors. Server 1315 tests,
client 19 tests — all green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pilot of phase 4 plus a libs/errs API change introduced after the
user pointed out that `code('buss::disposed')` repeats the module
name redundantly across every declaration.
libs/errs additions:
- New `ModuleSeed` branded type — string of the form `'<module>::'`
produced once per module.
- `moduleSeed(module)` factory: validates the module name and returns
a `ModuleSeed`.
- `errCode(parent, segment)` builder: composes a child `ErrCode` from
a `ModuleSeed` (uses `::` separator) or another `ErrCode` (uses `.`
separator). The builder picks the right separator automatically.
- `isModuleSeed(value)` discriminator.
- `matches(err, family)` now accepts `ModuleSeed | ErrCode`. Passing
a seed matches any error from that module; passing a code matches
hierarchically within the same module. Replaces the
`matchesModule(err, 'buss')` helper introduced earlier in this
session — that helper was redundant once seeds entered the API.
Sium pilot:
- arts/sium/consts.ts: declares `SIUM_ERR = moduleSeed('sium')` plus
the two child codes via `errCode(SIUM_ERR, 'validation')` and
`errCode(SIUM_ERR, 'async_schema')`. Module name appears exactly
once.
- arts/sium/core/types.ts: `SiumValidationError` and
`SiumAsyncSchemaError` extend `CodeError`. Hardcoded
`this.name = 'SiumValidationError'` literals removed. Subclass-
specific fields (`issues`, `schemaKind`) preserved.
- Adds `isSiumValidationError` / `isSiumAsyncSchemaError` guards
(closes audit-1-5 section 3.2 for sium).
- 12 tests in arts/sium/test/errors.test.ts cover subclass shape,
identity, `matches` against seed and exact code, and the fluent
decorator chain.
docs/conventions.md updated:
- Section 4 rewritten around the `moduleSeed`/`errCode` pattern.
- "Family root" wording removed (was misleading — `BUSS_ERR='buss::base'`
was a sibling, not an ancestor of its module's codes).
- `matches` documented as accepting either a seed or an ErrCode.
Verification: svelte-check 1403 files / 0 errors. Server 1315 tests
(+10 from previous), client 19 tests — all green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Phase 3 of the convention pass — introduces the framework's single
canonical error system, designed in dialogue with the user and
documented in docs/conventions.md section 4.
Public API:
- `ErrCode` — branded string type for `module::path.with.dots`
identifiers. Validated at construction via `code(value)` (throws
`CodeFormatError`) or `isValidCode(value)` predicate.
- Helpers: `moduleOf`, `leaf`, `parent`, `sub`, `parts`,
`isDescendantOf`, `isEqualOrDescendantOf`, `codeToLangPath`.
- `CodeError` — single error class for the framework. Carries a
required `ErrCode` (its identity), optional dev-facing `message`,
optional `cause`, and a frozen `meta` bag of contextual fields.
- Fluent immutable decorators: `withMessage`, `withTime`,
`withRequestId`, `withTenant`, `withUser`, `withData`, generic
`with(meta)`. Each returns a new `CodeError` with the same code —
identity is invariant under decoration.
- `isCodeError(value)` type guard.
- `matches(value, family)` family-membership predicate, the natural
way to catch `if (matches(err, BUSS_ERR))` for everything in the bus.
- `CodeFormatError` — bootstrap exception (does NOT extend CodeError
to break the circular construction dependency).
Format properties:
- `module::path.with.dots` — `::` separates module from hierarchy,
`.` separates segments inside the path, `_` allowed inside a single
segment as a word separator.
- Lowercase alphanumeric only. No uppercase, hyphens, slashes, spaces.
- Strict descendancy check respects segment boundaries:
`'buss::listener_extra'` is NOT a descendant of `'buss::listener'`.
- `codeToLangPath` swaps `::` for `.` so the same `ErrCode` can also
serve as the i18n path: `t(codeToLangPath(err.code))`.
Validation reasons exported as stable string constants
(`ERRS_VALIDATION_REASON_*`) so callers can branch on them
programmatically without pattern-matching error messages.
Tests: 62 in `code.test.ts` + 25 in `code-error.test.ts`. Cover
validation paths, all helpers, the fluent decorator chain, immutability,
toJSON shape, isCodeError discrimination across CodeError subclasses,
and matches() for identity / family / decoration cases.
This commit only adds `libs/errs/` — no existing module migrates yet.
Phase 4 pilots the new system in `arts/sium`.
Verification: svelte-check 1402 files / 0 errors. Server 1292 tests
(+62), client 19 tests — all green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Phase 2B.3 of the convention pass — closes the gap between rule 2
(`<MOD>_<CATEGORY>_<NAME>`) and the codebase. Adds the module's
4-letter alias to constants that previously had none or used a
non-canonical category prefix. ~190 constants renamed across 7
modules.
Bulk renames per module (sed with `\b...\b` word boundaries):
- arts/timr — ENGINE_METHOD_*, LOG_MSG_*, ERROR_PREFIX,
ERROR_NAME_*, ERROR_MSG_* now carry TIMR_ prefix
- arts/conn — TRANSPORT_KIND_*, FRAME_KEY_*, DEFAULT_*,
TIMR_KEY_*, BROWSER_EVENT_*, DOCUMENT_*,
WEBSOCKET_*, MOCK_TRANSPORT_*, LOG_MSG_*,
ERROR_*, FRAME_TYPE_*, METHOD_*, CLOSE_REASON_*
etc. now carry CONN_ prefix
- arts/sess — DEFAULT_*, AUTO_REFRESH_TIMER_KEY,
BROWSER_EVENT_*, DOCUMENT_*, BROADCAST_TYPE,
IDENTITY_*, REVOKE_SCOPE_*, REFRESH_STATUS_*,
ADOPT_REASON_*, SKIP_REASON_*, REVOKE_REASON_*,
INVARIANT_*, ACTOR_*, FIELD_*, ENGINE_METHOD_*,
ERROR_PREFIX/NAME/MSG, LOG_MSG_*, EVENT_* (the
lifecycle ones — see disambiguation below) now
carry SESS_ prefix
- arts/stor — ENTRY_CHANGE_SOURCE_*, DEFAULT_*, BROWSER_EVENT_*,
ENVELOPE_KEY/ERROR_*, NAMESPACE_SEPARATOR now
carry STOR_ prefix
- arts/http — DEFAULT_RETRY*, RETRY_AFTER_HEADERS,
DEFAULT_TIMEOUT, MAX_ERROR_BODY_BYTES, LOG_MSG_*,
ERROR_*, TIMEOUT_SCOPE_*, RESULT_KIND_* now
carry HTTP_ prefix
- arts/fmts — DEFAULT_LOCALE, AUTO_VALUE → FMTS_DEFAULT_LOCALE,
FMTS_AUTO_VALUE
- libs/timers — DEFAULT_BACKOFF_* → TIMR_DEFAULT_BACKOFF_*
- libs/lang — 4 unprefixed → LANG_ prefix
- libs/cach — 1 unprefixed → CACH_ prefix
Lifecycle vs bus event disambiguation (sess):
`arts/sess` had two distinct constant sets that collided after the
prefix add: `EVENT_*` (lifecycle, value `'sess.lifecycle.X'`) and
`SESS_EVENT_*` (bus, value `'sess.X'`). Both ended up with the same
SESS_EVENT_* name. To preserve the distinction:
- Lifecycle declarations renamed to SESS_EVENT_LIFECYCLE_* (matching
the path component already in their values).
- Bus declarations stay as SESS_EVENT_*.
- Consumers split correctly: code that switches on `change.event`
uses LIFECYCLE_ variants; code that publishes/subscribes to bus
uses bus variants.
Conn-side lifecycle redeclarations (`SESS_EVENT_REFRESHED` etc. with
`'sess.lifecycle.X'` values inside arts/conn/consts.ts) became
CONN_SESS_EVENT_* — these are conn-local copies; future cleanup
should import from sess instead of redeclaring.
Verification: svelte-check 1395 / 0 errors. Server 1230 tests, client
19 tests — all green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Phase 2B.2 of the convention pass. Closes the inconsistency where
arts/aapp used APP_* prefix while libs/aapp already used AAPP_*.
After this commit every constant under arts/aapp and libs/aapp uses
the canonical 4-letter alias `AAPP_` (rule 1 of docs/conventions.md).
Constants renamed (~24 total):
- APP_EVENT_* → AAPP_EVENT_* (the 6 public events)
- APP_USER_IDENTITY_CAUSE_* → AAPP_USER_IDENTITY_CAUSE_*
- APP_ORCHESTRATION_* → AAPP_ORCHESTRATION_*
- APP_ERROR_* → AAPP_ERROR_*
- APP_LOG_MSG_* → AAPP_LOG_MSG_*
- APP_CONNECTION_CLOSE_REASON_* → AAPP_CONNECTION_CLOSE_REASON_*
- APP_EVENT_RUNTIMES → AAPP_EVENT_RUNTIMES
Wire-format change for the public app event values:
- 'app.user.identity.changed' → 'aapp.user.identity.changed'
- 'app.tenant.switched' → 'aapp.tenant.switched'
- 'app.permissions.refresh.requested'→ 'aapp.permissions.refresh.requested'
- 'app.connectivity.changed' → 'aapp.connectivity.changed'
- 'app.cache.invalidate.requested' → 'aapp.cache.invalidate.requested'
- 'app.dispose.starting' → 'aapp.dispose.starting'
Per docs/conventions.md rule 5, every event-identifier string value
must start with the module's 4-letter alias. Now that AAPP_MODULE = 'aapp'
(set in phase 2B.1) is the canonical module identifier, the event
scope follows. External observers of these events must update string
filters from `app.*` to `aapp.*`. The framework has not been tagged 0.1
yet so the wire format is still in flight.
Translation keys (`'app.title'`, `'app.cart'`, `'app.boot'`, etc. used
by `App.Lang.t(...)` in the demo / ecosystem test pages) are NOT
events and were intentionally left untouched — they're paths in the
lang schema, independent of the AAPP module identity.
Verification: svelte-check 1395 / 0 errors. Server 1230 tests, client
19 tests — all green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Phase 2B.1 of the convention pass. Establishes one canonical constant
per module — `<MOD>_MODULE = '<alias>'` — as the single source for the
module's identifier across logger category, error message prefixes,
event scopes, and any other place the module's name is needed.
What changed:
1. Renamed all `<MOD>_LOG_CATEGORY` constants to `<MOD>_MODULE` (the
value semantics didn't change; only the name). Affected modules:
buss, conn, sess, perm (libs+arts+svrs), timr, lang, auth, http,
sium, cach, stor, aapp (libs+arts), and the four fmts sub-modules
(fmts, fmts.curr, fmts.dates, fmts.nums, fmts.unts).
2. Aligned values with the 4-letter alias where they didn't already:
- STOR_MODULE: 'storage' → 'stor'
- FMTS_MODULE: 'formats' → 'fmts'
- FMTS_CURR_MODULE: 'formats.currency' → 'fmts.curr'
- FMTS_DATES_MODULE: 'formats.dates' → 'fmts.dates'
- FMTS_NUMS_MODULE: 'formats.numbers' → 'fmts.nums'
- FMTS_UNTS_MODULE: 'formats.units' → 'fmts.unts'
3. Unified the duplicate `AAPP_MODULE` declaration: arts/aapp/consts.ts
now re-exports from libs/aapp/consts.ts (canonical source). Both
files used to declare it independently with different values
('app' vs 'aapp').
4. Replaced hardcoded `'[<alias>] ...'` literals in error messages
with template strings using `<MOD>_MODULE`. Every error-message
constant now derives the prefix from the module identifier instead
of hardcoding it. Affected files: libs/aapp/consts.ts, arts/aapp/consts.ts,
libs/buss/consts.ts, libs/lang/errors.ts, arts/stor/errors.ts,
arts/sium/errors.ts, arts/fmts/errors.ts, and the ERROR_PREFIX
constants in arts/conn, arts/sess, arts/http, arts/timr.
5. Updated diagnostic event values to use the new module aliases:
- STOR_DIAGNOSTIC_EVENTS.ERROR: 'storage.error' → 'stor.error'
- All FMTS_*_DIAGNOSTIC_EVENTS values to use 'fmts.X.*'
6. Updated tests that asserted against the old values (storage-integration.test
and fmts/curr/test/barrel.test).
7. Updated docs/conventions.md: replaced the LOG_CATEGORY category
with the new MODULE category. Added the rule that ERROR_MSG values
must use the template `[${<MOD>_MODULE}]`, never a hardcoded literal.
Verification: svelte-check 1395 / 0 errors. Server 1230 tests, client
19 tests — all green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Phase 2 of the convention pass documented in docs/conventions.md.
Aligns every module-level constant's prefix with the bundler alias
that already identifies the artifact (rule 1 of the convention):
- BUS_* → BUSS_* (libs/buss + arts/buss)
- CONNECTION_* → CONN_* (arts/conn + web consumers)
- SESSION_* → SESS_* (arts/sess + libs/aapp + consumers)
- PERMISSION_* → PERM_* (arts/perm, libs/perm, svrs/perm)
- TIMER_* → TIMR_* (arts/timr + libs/timers)
- CACHE_* → CACH_* (arts/cach + libs/cach + svrs/cach)
- STORAGE_* → STOR_* (arts/stor + consumers)
Mechanical sed pass with `\b<OLD>_` word-boundary anchor — this only
matches at identifier start, never inside (e.g. AAPP_BUS_CONTEXT_KEY
stays untouched because the boundary requirement is between non-word
and word characters).
Out of scope and deferred to phase 2B (per-module decisions, not
bulk-applicable):
- LOGGER_CATEGORY constants in each module's consts.ts must become
the module's own LOG_CATEGORY (BUSS_LOG_CATEGORY = 'buss',
CONN_LOG_CATEGORY = 'conn', etc.) — different rename per module,
not a single sed pattern.
- APP_* → AAPP_* (arts/aapp uses APP_ today; libs/aapp already
uses AAPP_).
- Ad-hoc constants without module prefix (DEFAULT_TIMER_*,
EVENT_*, BROWSER_*, IDENTITY_*, ACTOR_*, REVOKE_SCOPE_*, etc. in
arts/sess/consts.ts; AUTO_REAUTH_* in arts/conn).
Note on web/ files:
- src/web/routes/active/get-started/ai-agents/+page.svelte
- src/web/routes/temp/c2/+page.svelte
- src/web/routes/temp/c2/Curtain.svelte
These three files contain pre-existing user modifications (work in
progress unrelated to this rename) that the bulk sed touched on top
because they referenced renamed identifiers. Excluding them would
break compilation. Their content here is the intersection of both
changes; the user's prior edits to these files are intentionally
bundled in this commit.
Verification: svelte-check 1395 files / 0 errors. Server 1230 tests,
client 19 tests — all green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Working documents and audits were spread across the project root,
mixing with standard npm/GitHub files (README, CHANGELOG, CONTRIBUTING,
SECURITY, BRAND). Moves them under docs/ for a clean root and adds
docs/conventions.md as the canonical document for codebase-wide
naming and structure rules.
Files moved to docs/ (via git mv, history preserved):
- audit-1-5.md (current ecosystem audit)
- AUDIT_KIMI.md
- AUDIT_OPENCODE.md
- AUDIT_claude.md (historical audits from prior tools)
- before_0_1.md (pre-0.1 release checklist)
- buss.md (bus design doc, no longer live)
- NEXT_STEPS.md (roadmap)
Files staying in root (npm/GitHub convention):
- README.md, CHANGELOG.md, CONTRIBUTING.md, SECURITY.md, BRAND.md
References updated to point at docs/:
- CHANGELOG.md (line 11)
- README.md (line 105)
- SECURITY.md (line 3)
- src/web/routes/active/security/+page.svelte (line 46)
docs/conventions.md captures three rules accepted as binding for the
codebase:
1. Module identifier — every artifact and lib uses its 4-letter alias
(BUSS, CONN, SESS, PERM, TIMR, LOGR, CACH, STOR, FMTS, FEND, ADOM,
AAPP, AUTH, LANG, HTTP, SIUM, ERRS) for both string values and
constant name prefixes. Drift from this rule (BUS_*, CONNECTION_*,
SESSION_*, …) is being closed in the next audit pass.
2. Constant naming — `<MOD>_<CATEGORY>_<NAME>` strictly. No
exceptions (no DEFAULT_TIMER_* style).
3. Category vocabulary — fixed list of category tokens (ERR, EVENT,
DIAGNOSTIC_EVENTS, METHOD, STATE, STATUS, KIND, REASON, TYPE, MODE,
DEFAULT, LIMIT, ID_PREFIX, LOG_CATEGORY, LOG_MSG, ERROR_MSG,
ERROR_NAME, CONTEXT_KEY). Ad-hoc categories (AUTO_REAUTH,
AUTO_INVALIDATE, BUFFER_POLICY, CHANNEL_STATE) fold into one of
these.
The document also formalizes the layer rules and ErrCode shape that
will be implemented in upcoming commits.
svelte-check 1395/0 errors. No code-side regressions; the moves are
file-only.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
audit-1-5.md section 2: 46 values were emitted as bare strings
(`'auth_failed'`, `'listener_threw'`, `'check'`) and collided across
artifacts in any aggregated log stream. Each value now carries its
module prefix so the type is self-describing in isolation and never
clashes with another emitter.
- arts/conn/consts.ts (CONNECTION_DIAGNOSTIC_EVENTS) — 15 values → conn.*
- arts/sess/consts.ts (SESSION_DIAGNOSTIC_EVENTS) — 15 values → sess.*
- arts/perm/consts.ts (PERMISSION_CLIENT_DIAGNOSTIC_EVENTS) — 3 → perm.client.*
- svrs/perm/consts.ts (PERMISSION_DIAGNOSTIC_EVENTS) — 3 → perm.server.*
- svrs/perm/consts.ts (PERMISSION_METHOD_*) — 7 → perm.* (aligns with
the client-side counterpart in arts/perm/consts.ts which already used
this scoping)
- libs/timers/consts.ts (TIMER_DIAGNOSTIC_EVENTS) — 3 values → timr.*
The rule was already documented in arts/perm/consts.ts ("scoped with
the artifact prefix `perm.` so that aggregated diagnostic streams do
not collide"); these six files were the modules that hadn't been
brought into compliance.
Real collisions resolved today: `'listener_threw'` (3 emitters: conn
+ sess + timr), `'session_revoked'` and `'session_expired'` (conn
bridge + sess lifecycle).
Consumers reference the constants by symbol (`CONNECTION_DIAGNOSTIC_EVENTS.AUTH_FAILED`,
not `'auth_failed'`), so this is a transparent rename. svelte-check
1395/0 errors; server 1230 tests; client 19 tests — all green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Layer-boundary cleanup (audit-1-5.md section 1):
- fend → adom: move apply.ts to libs/dom; FrontendDom is now DomApplier;
fend falls back to bare applyChange instead of constructing ActiveDom
- sium → lang: full split — pure code (consts, types, guards, helpers,
errors, json, plural, plural_rules, diagnostics) moves to libs/lang;
arts/lang keeps engine + active wrappers and re-exports for back-compat
- conn → timr: minimum split — types and public constants move to
libs/timers; conn imports types from $libs/timers; EngineConnectionsOptions.timers
is now required (no more silent createEngineTimers fallback). Tests
updated to construct shared timers per beforeEach
Bus contract finishing touches (continued from prior session):
- subscribe() returns the unsubscribe function directly
- publishCausedBy() propagates correlationId/causationId
- invokeListener hook + Svelte adapter wraps listeners in untrack
- maxReentrancyDepth guard with BusReentrancyLimitError (fatal — bypasses
listener-error trap)
- DEV-mode structuredClone payload check raising BusInvalidPayloadError
- BusListenerFailure carries envelopeId/correlationId/causationId
- createBusRecent active wrapper, bus-context.svelte.ts, APP_EVENT_RUNTIMES
table with assertEventCanFire wired into every publishApp* helper
- App switches to createSvelteEngineBus
audit-1-5.md captures the full ecosystem audit (5 axes); section 1 is
now closed by these changes. Sections 2-5 remain open.
Verification: svelte-check 1395/0 errors; server 1230 tests passed;
client 19 tests passed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>