|
|
|
|
@ -0,0 +1,204 @@
|
|
|
|
|
# Active conventions
|
|
|
|
|
|
|
|
|
|
This document captures the **mandatory naming and structure
|
|
|
|
|
conventions** for the Active framework codebase. Every new module,
|
|
|
|
|
type, constant, and file must comply. Existing code that drifts from
|
|
|
|
|
these rules is treated as audit debt and migrated module by module.
|
|
|
|
|
|
|
|
|
|
The goal is single-rule homogeneity: a developer learns the convention
|
|
|
|
|
once and applies it everywhere. No exceptions without an explicit
|
|
|
|
|
decision recorded here.
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 1. Module identifier — 4-letter alias
|
|
|
|
|
|
|
|
|
|
Every artifact and lib that pairs with one is identified by a stable
|
|
|
|
|
**4-letter alias** that already lives in `svelte.config.js` as a
|
|
|
|
|
bundler alias (`$buss`, `$conn`, `$sess`, …).
|
|
|
|
|
|
|
|
|
|
The same alias is the canonical module identifier across the codebase:
|
|
|
|
|
|
|
|
|
|
- **Path scoping in string values** (already enforced after audit
|
|
|
|
|
section 2): `'buss.event.published'`, `'conn.auth_failed'`,
|
|
|
|
|
`'sess.lifecycle.adopted'`, `'perm.client.remote_check_failed'`.
|
|
|
|
|
- **Constant name prefix**: `BUSS_*`, `CONN_*`, `SESS_*`, `PERM_*`,
|
|
|
|
|
`TIMR_*`, `LOGR_*`, `CACH_*`, `STOR_*`, `FMTS_*`, `FEND_*`, `ADOM_*`,
|
|
|
|
|
`AAPP_*`, `AUTH_*`, `LANG_*`, `HTTP_*`, `SIUM_*`, `ERRS_*`.
|
|
|
|
|
|
|
|
|
|
Forbidden: full English words like `BUS_*`, `CONNECTION_*`, `SESSION_*`,
|
|
|
|
|
`PERMISSION_*`, `TIMER_*`, `LOGGER_*`, `CACHE_*`, `STORAGE_*`,
|
|
|
|
|
`FORMATS_*`, `FRONTEND_*`. Drift on this axis is being closed in a
|
|
|
|
|
dedicated audit pass.
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 2. Constant naming — `<MOD>_<CATEGORY>_<NAME>`
|
|
|
|
|
|
|
|
|
|
Every categorical module-level constant follows the pattern:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
<MOD>_<CATEGORY>_<NAME>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
- **`<MOD>`** — the module's 4-letter alias in caps (rule 1).
|
|
|
|
|
- **`<CATEGORY>`** — what kind of constant it is. Picked from the
|
|
|
|
|
fixed vocabulary in section 3.
|
|
|
|
|
- **`<NAME>`** — the specific value's identifier in
|
|
|
|
|
`UPPER_SNAKE_CASE`.
|
|
|
|
|
|
|
|
|
|
### Examples
|
|
|
|
|
|
|
|
|
|
```ts
|
|
|
|
|
// good
|
|
|
|
|
BUSS_DIAGNOSTIC_EVENTS
|
|
|
|
|
BUSS_DEFAULT_MAX_LISTENERS_PER_EVENT
|
|
|
|
|
BUSS_ERR_DISPOSED
|
|
|
|
|
SESS_EVENT_LIFECYCLE_ADOPTED
|
|
|
|
|
PERM_METHOD_CHECK
|
|
|
|
|
TIMR_STATE_PENDING
|
|
|
|
|
CONN_REASON_AUTH_FAILED
|
|
|
|
|
CACH_LIMIT_DEFAULT_MAX_ENTRIES
|
|
|
|
|
STOR_LOG_CATEGORY
|
|
|
|
|
|
|
|
|
|
// bad (will be flagged in audit)
|
|
|
|
|
BUS_DIAGNOSTIC_EVENTS // wrong module prefix (rule 1)
|
|
|
|
|
DEFAULT_TIMER_SCOPE_SEPARATOR // category before module (rule 2)
|
|
|
|
|
PERMISSION_METHOD_CHECK // wrong module prefix (rule 1)
|
|
|
|
|
AUTO_REAUTH_USER_IDENTITY_CHANGE // missing module prefix (rule 1)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Sub-categories
|
|
|
|
|
|
|
|
|
|
When a category needs internal hierarchy, append additional segments
|
|
|
|
|
in the `<NAME>` part, not in `<CATEGORY>`:
|
|
|
|
|
|
|
|
|
|
```ts
|
|
|
|
|
// good
|
|
|
|
|
BUSS_LISTENER_ERROR_MODE_THROW
|
|
|
|
|
SESS_EVENT_LIFECYCLE_ADOPTED
|
|
|
|
|
SESS_EVENT_LIFECYCLE_REVOKED
|
|
|
|
|
PERM_DEFAULT_REMOTE_FAILURE_BACKOFF_MS
|
|
|
|
|
|
|
|
|
|
// bad
|
|
|
|
|
BUSS_LISTENER_ERR_MODE_THROW // category split across underscores
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 3. Category vocabulary — fixed list
|
|
|
|
|
|
|
|
|
|
Only these category tokens are allowed. Adding a new category is a
|
|
|
|
|
deliberate decision recorded in this document, not an ad-hoc choice
|
|
|
|
|
inside a module.
|
|
|
|
|
|
|
|
|
|
| Category | Use |
|
|
|
|
|
|---|---|
|
|
|
|
|
| `ERR` | Error codes (`ErrCode` values from `$libs/errs`) |
|
|
|
|
|
| `EVENT` | Bus or lifecycle event names (string discriminators) |
|
|
|
|
|
| `DIAGNOSTIC_EVENTS` | Event values published through `Logger` (catalog object) |
|
|
|
|
|
| `METHOD` | Method labels for error messages (`ensureLive(METHOD)`) |
|
|
|
|
|
| `STATE` | Tagged-union state discriminators |
|
|
|
|
|
| `STATUS` | Tagged-union status discriminators |
|
|
|
|
|
| `KIND` | Tagged-union kind discriminators |
|
|
|
|
|
| `REASON` | Tagged-union reason discriminators |
|
|
|
|
|
| `TYPE` | Tagged-union type discriminators (when none of the above fits) |
|
|
|
|
|
| `MODE` | Mode discriminators (e.g. listener error mode) |
|
|
|
|
|
| `DEFAULT` | Default values for options |
|
|
|
|
|
| `LIMIT` | Maximum / minimum values |
|
|
|
|
|
| `ID_PREFIX` | Prefix used by ID factories |
|
|
|
|
|
| `LOG_CATEGORY` | The logger category string |
|
|
|
|
|
| `LOG_MSG` | Log message strings |
|
|
|
|
|
| `ERROR_MSG` | Error message strings (technical, dev-facing) |
|
|
|
|
|
| `ERROR_NAME` | Legacy `Error.name` strings (being replaced by `ERR` codes) |
|
|
|
|
|
| `CONTEXT_KEY` | Svelte context keys |
|
|
|
|
|
|
|
|
|
|
Categories that are **not** in this list (e.g. `AUTO_REAUTH`,
|
|
|
|
|
`AUTO_INVALIDATE`, `BACKOFF`, `BUFFER_POLICY`, `CHANNEL_STATE`) must
|
|
|
|
|
fold into one of the above. Examples:
|
|
|
|
|
|
|
|
|
|
- `CONNECTION_AUTO_REAUTH_*` → `CONN_REASON_AUTO_REAUTH_*` if the value
|
|
|
|
|
drives a "why this happened" branch, or `CONN_MODE_AUTO_REAUTH_*` if
|
|
|
|
|
it configures behavior.
|
|
|
|
|
- `CACHE_AUTO_INVALIDATE_*` → `CACH_MODE_AUTO_INVALIDATE_*`.
|
|
|
|
|
- `CONN_BUFFER_POLICY_*` → `CONN_MODE_BUFFER_*`.
|
|
|
|
|
|
|
|
|
|
When in doubt, propose the addition here before introducing it.
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 4. Error codes (`ErrCode`) — special case under rule 2
|
|
|
|
|
|
|
|
|
|
Error codes from `$libs/errs` follow rule 2 with category `ERR`:
|
|
|
|
|
|
|
|
|
|
```ts
|
|
|
|
|
import { code, type ErrCode } from '$libs/errs';
|
|
|
|
|
|
|
|
|
|
export const BUSS_ERR: ErrCode = code('buss::base'); // family root
|
|
|
|
|
export const BUSS_ERR_DISPOSED: ErrCode = code('buss::disposed');
|
|
|
|
|
export const BUSS_ERR_INVALID_PAYLOAD: ErrCode = code('buss::invalid_payload');
|
|
|
|
|
export const BUSS_ERR_LISTENER: ErrCode = code('buss::listener'); // sub-family root
|
|
|
|
|
export const BUSS_ERR_LISTENER_FAILED: ErrCode = code('buss::listener.failed');
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The string value's path segments mirror the constant's `<NAME>` part:
|
|
|
|
|
`BUSS_ERR_LISTENER_FAILED` ↔ `'buss::listener.failed'`.
|
|
|
|
|
|
|
|
|
|
The `::` separator inside the string distinguishes module from
|
|
|
|
|
hierarchy. The constant uses `_` as the syntactic separator (rule 2).
|
|
|
|
|
A helper `codeToLangPath(c)` converts `'buss::listener.failed'` →
|
|
|
|
|
`'buss.listener.failed'` for the i18n path.
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 5. String values inside diagnostic / event constants
|
|
|
|
|
|
|
|
|
|
Already enforced after audit section 2:
|
|
|
|
|
|
|
|
|
|
```ts
|
|
|
|
|
// good — value carries the module scope
|
|
|
|
|
export const CONN_DIAGNOSTIC_EVENTS = {
|
|
|
|
|
AUTH_FAILED: 'conn.auth_failed',
|
|
|
|
|
RECONNECT_EXHAUSTED: 'conn.reconnect_exhausted'
|
|
|
|
|
} as const;
|
|
|
|
|
|
|
|
|
|
// bad — bare value collides across modules
|
|
|
|
|
export const CONN_DIAGNOSTIC_EVENTS = {
|
|
|
|
|
AUTH_FAILED: 'auth_failed', // collides with auth.* events
|
|
|
|
|
LISTENER_THREW: 'listener_threw' // collides with sess and timr
|
|
|
|
|
} as const;
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Rule: every string value emitted as an event identifier must start
|
|
|
|
|
with the module's 4-letter alias (rule 1) followed by `.` and the
|
|
|
|
|
value-specific path.
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 6. File and folder structure
|
|
|
|
|
|
|
|
|
|
| Layer | Rule |
|
|
|
|
|
|---|---|
|
|
|
|
|
| `libs/<mod>/` | Pure contracts: types, constants, error classes, helpers. No Svelte runes, no engine state. |
|
|
|
|
|
| `arts/<mod>/` | Runtime engine + `*.svelte.ts` active wrappers. May import from `$libs/<mod>` and from its own files. |
|
|
|
|
|
| `arts/<mod>/index.ts` | Public barrel. Re-exports the artifact's surface. |
|
|
|
|
|
| `arts/<mod>/test/` | Tests for engine and active wrappers. |
|
|
|
|
|
| `svrs/<mod>/` | Server-side counterparts (cookies, db adapters, route handlers). |
|
|
|
|
|
| `arts/aapp/` | Composition root. Allowed to import any `$<mod>`. |
|
|
|
|
|
|
|
|
|
|
**Cross-artifact imports are forbidden** (`arts/X` cannot import
|
|
|
|
|
`$Y`). Sole exception: `arts/aapp/`.
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 7. When this document is updated
|
|
|
|
|
|
|
|
|
|
- A new category in section 3 requires a record-of-decision: who, when,
|
|
|
|
|
why.
|
|
|
|
|
- Module aliases are frozen: a new artifact picks a 4-letter alias
|
|
|
|
|
not yet taken; renaming an existing alias is a breaking change.
|
|
|
|
|
- Drift found in the codebase that violates these rules is filed as an
|
|
|
|
|
audit finding and resolved in a dedicated commit.
|
|
|
|
|
|
|
|
|
|
Last updated: `2026-05-02` — initial version after audit-1-5.md
|
|
|
|
|
sections 1–2 closed.
|