Rename APP_* constants to AAPP_* and align event values to aapp.*

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>
master
dev 5 months ago
parent a01ef0f63d
commit 838d000f63

@ -32,17 +32,17 @@ import {
import { createAuthCacheInvalidator } from './integrations/auth-cache';
import { wireSessionTranslator } from './integrations/session-translator';
import {
APP_ERROR_ALREADY_CREATED_PERMISSIONS,
APP_ERROR_ALREADY_CREATED_AUTH,
APP_ERROR_ALREADY_CREATED_SESSION,
APP_ERROR_CREATE_PERMISSIONS_ENDPOINT_REQUIRED,
APP_ORCHESTRATION_SILENT,
APP_ORCHESTRATION_STANDARD,
APP_ORCHESTRATION_TRANSLATOR_CONNECTIVITY,
APP_ORCHESTRATION_TRANSLATOR_DISPOSE,
APP_ORCHESTRATION_TRANSLATOR_IDENTITY,
APP_ORCHESTRATION_TRANSLATOR_PERMISSIONS_REFRESH,
APP_ORCHESTRATION_TRANSLATOR_TENANT_SWITCHED,
AAPP_ERROR_ALREADY_CREATED_PERMISSIONS,
AAPP_ERROR_ALREADY_CREATED_AUTH,
AAPP_ERROR_ALREADY_CREATED_SESSION,
AAPP_ERROR_CREATE_PERMISSIONS_ENDPOINT_REQUIRED,
AAPP_ORCHESTRATION_SILENT,
AAPP_ORCHESTRATION_STANDARD,
AAPP_ORCHESTRATION_TRANSLATOR_CONNECTIVITY,
AAPP_ORCHESTRATION_TRANSLATOR_DISPOSE,
AAPP_ORCHESTRATION_TRANSLATOR_IDENTITY,
AAPP_ORCHESTRATION_TRANSLATOR_PERMISSIONS_REFRESH,
AAPP_ORCHESTRATION_TRANSLATOR_TENANT_SWITCHED,
AAPP_MODULE
} from './consts.ts';
import { AappAlreadyCreatedError } from './errors.ts';
@ -121,7 +121,7 @@ export function createActiveApp<S extends LangNode = LangNode>(
clock: Timers.clock
});
const orchestration = resolveActiveAppOrchestration(options.orchestration);
const detachSessionTranslator = orchestration.has(APP_ORCHESTRATION_TRANSLATOR_IDENTITY)
const detachSessionTranslator = orchestration.has(AAPP_ORCHESTRATION_TRANSLATOR_IDENTITY)
? wireSessionTranslator(Bus)
: undefined;
@ -178,7 +178,7 @@ export function createActiveApp<S extends LangNode = LangNode>(
sessOptions: Omit<EngineSessionOptions<TUser, TCredential, TData>, 'logger' | 'bus'> = {}
): ActiveSession<TUser, TCredential, TData> {
if (Sess !== undefined) {
throw new SessAlreadyCreatedError(APP_ERROR_ALREADY_CREATED_SESSION);
throw new SessAlreadyCreatedError(AAPP_ERROR_ALREADY_CREATED_SESSION);
}
const built = createActiveSession<TUser, TCredential, TData>({
...sessOptions,
@ -210,14 +210,14 @@ export function createActiveApp<S extends LangNode = LangNode>(
permissionOptions: Partial<Omit<ActivePermissionsOptions, 'logger' | 'http' | 'bus'>> = {}
): ActivePermissions {
if (Permissions !== undefined) {
throw new AappAlreadyCreatedError(APP_ERROR_ALREADY_CREATED_PERMISSIONS);
throw new AappAlreadyCreatedError(AAPP_ERROR_ALREADY_CREATED_PERMISSIONS);
}
const merged = {
...options.permissions,
...permissionOptions
};
if (!merged.endpoint) {
throw new PermInvalidEndpointError(APP_ERROR_CREATE_PERMISSIONS_ENDPOINT_REQUIRED);
throw new PermInvalidEndpointError(AAPP_ERROR_CREATE_PERMISSIONS_ENDPOINT_REQUIRED);
}
const built = createActivePermissionsClient({
...merged,
@ -234,7 +234,7 @@ export function createActiveApp<S extends LangNode = LangNode>(
authOptions: Omit<ActiveAuthOptions, 'http' | 'cach' | 'logger'> = {}
): ActiveAuth {
if (Auth !== undefined) {
throw new AappAlreadyCreatedError(APP_ERROR_ALREADY_CREATED_AUTH);
throw new AappAlreadyCreatedError(AAPP_ERROR_ALREADY_CREATED_AUTH);
}
const built = createActiveAuth({
...options.auth,
@ -253,7 +253,7 @@ export function createActiveApp<S extends LangNode = LangNode>(
dispose() {
if (disposed) return;
disposed = true;
if (orchestration.has(APP_ORCHESTRATION_TRANSLATOR_DISPOSE)) {
if (orchestration.has(AAPP_ORCHESTRATION_TRANSLATOR_DISPOSE)) {
publishAppDisposeStarting(Bus, { cause: AAPP_MODULE });
}
Auth?.dispose();
@ -284,19 +284,19 @@ export function createActiveApp<S extends LangNode = LangNode>(
function resolveActiveAppOrchestration(
orchestration: ActiveAppOrchestrationOptions | undefined
): ReadonlySet<ActiveAppOrchestrationTranslator> {
if (orchestration === false || orchestration === APP_ORCHESTRATION_SILENT) {
if (orchestration === false || orchestration === AAPP_ORCHESTRATION_SILENT) {
return new Set();
}
if (orchestration === undefined || orchestration === APP_ORCHESTRATION_STANDARD) {
if (orchestration === undefined || orchestration === AAPP_ORCHESTRATION_STANDARD) {
return new Set(STANDARD_ORCHESTRATION_TRANSLATORS);
}
return new Set(orchestration);
}
const STANDARD_ORCHESTRATION_TRANSLATORS = [
APP_ORCHESTRATION_TRANSLATOR_IDENTITY,
APP_ORCHESTRATION_TRANSLATOR_PERMISSIONS_REFRESH,
APP_ORCHESTRATION_TRANSLATOR_TENANT_SWITCHED,
APP_ORCHESTRATION_TRANSLATOR_CONNECTIVITY,
APP_ORCHESTRATION_TRANSLATOR_DISPOSE
AAPP_ORCHESTRATION_TRANSLATOR_IDENTITY,
AAPP_ORCHESTRATION_TRANSLATOR_PERMISSIONS_REFRESH,
AAPP_ORCHESTRATION_TRANSLATOR_TENANT_SWITCHED,
AAPP_ORCHESTRATION_TRANSLATOR_CONNECTIVITY,
AAPP_ORCHESTRATION_TRANSLATOR_DISPOSE
] as const;

@ -1,28 +1,28 @@
export { AAPP_MODULE } from '$libs/aapp/consts';
import { AAPP_MODULE } from '$libs/aapp/consts';
export const APP_LOG_MSG_SESSION_CACHE_CLEAR_FAILED =
export const AAPP_LOG_MSG_SESSION_CACHE_CLEAR_FAILED =
'session change cache clear failed';
export const APP_CONNECTION_CLOSE_REASON_IDENTITY_CLEARED = 'identity_cleared';
export const AAPP_CONNECTION_CLOSE_REASON_IDENTITY_CLEARED = 'identity_cleared';
export const APP_ORCHESTRATION_STANDARD = 'standard';
export const APP_ORCHESTRATION_SILENT = 'silent';
export const APP_ORCHESTRATION_TRANSLATOR_IDENTITY = 'identity';
export const APP_ORCHESTRATION_TRANSLATOR_PERMISSIONS_REFRESH = 'permissions-refresh';
export const APP_ORCHESTRATION_TRANSLATOR_TENANT_SWITCHED = 'tenant-switched';
export const APP_ORCHESTRATION_TRANSLATOR_CONNECTIVITY = 'connectivity';
export const APP_ORCHESTRATION_TRANSLATOR_DISPOSE = 'dispose';
export const AAPP_ORCHESTRATION_STANDARD = 'standard';
export const AAPP_ORCHESTRATION_SILENT = 'silent';
export const AAPP_ORCHESTRATION_TRANSLATOR_IDENTITY = 'identity';
export const AAPP_ORCHESTRATION_TRANSLATOR_PERMISSIONS_REFRESH = 'permissions-refresh';
export const AAPP_ORCHESTRATION_TRANSLATOR_TENANT_SWITCHED = 'tenant-switched';
export const AAPP_ORCHESTRATION_TRANSLATOR_CONNECTIVITY = 'connectivity';
export const AAPP_ORCHESTRATION_TRANSLATOR_DISPOSE = 'dispose';
export const APP_ERROR_NAME_ALREADY_CREATED = 'AappAlreadyCreatedError';
export const AAPP_ERROR_NAME_ALREADY_CREATED = 'AappAlreadyCreatedError';
export const APP_ERROR_ALREADY_CREATED_SESSION =
export const AAPP_ERROR_ALREADY_CREATED_SESSION =
`[${AAPP_MODULE}] App.createActiveSession() called twice — only one session per App.`;
export const APP_ERROR_ALREADY_CREATED_PERMISSIONS =
export const AAPP_ERROR_ALREADY_CREATED_PERMISSIONS =
`[${AAPP_MODULE}] App.createActivePermissions() called twice — only one permissions client per App.`;
export const APP_ERROR_ALREADY_CREATED_AUTH =
export const AAPP_ERROR_ALREADY_CREATED_AUTH =
`[${AAPP_MODULE}] App.createActiveAuth() called twice — only one active auth client per App.`;
export const APP_ERROR_CREATE_PERMISSIONS_ENDPOINT_REQUIRED =
export const AAPP_ERROR_CREATE_PERMISSIONS_ENDPOINT_REQUIRED =
`[${AAPP_MODULE}] App.createActivePermissions() requires endpoint via options.permissions or argument.`;

@ -1,7 +1,7 @@
import { APP_ERROR_NAME_ALREADY_CREATED } from './consts.ts';
import { AAPP_ERROR_NAME_ALREADY_CREATED } from './consts.ts';
export class AappAlreadyCreatedError extends Error {
override readonly name = APP_ERROR_NAME_ALREADY_CREATED;
override readonly name = AAPP_ERROR_NAME_ALREADY_CREATED;
}
export function isAappAlreadyCreatedError(error: unknown): error is AappAlreadyCreatedError {

@ -1,12 +1,12 @@
export { createActiveApp } from './active-app.svelte';
export {
APP_ORCHESTRATION_SILENT,
APP_ORCHESTRATION_STANDARD,
APP_ORCHESTRATION_TRANSLATOR_CONNECTIVITY,
APP_ORCHESTRATION_TRANSLATOR_DISPOSE,
APP_ORCHESTRATION_TRANSLATOR_IDENTITY,
APP_ORCHESTRATION_TRANSLATOR_PERMISSIONS_REFRESH,
APP_ORCHESTRATION_TRANSLATOR_TENANT_SWITCHED,
AAPP_ORCHESTRATION_SILENT,
AAPP_ORCHESTRATION_STANDARD,
AAPP_ORCHESTRATION_TRANSLATOR_CONNECTIVITY,
AAPP_ORCHESTRATION_TRANSLATOR_DISPOSE,
AAPP_ORCHESTRATION_TRANSLATOR_IDENTITY,
AAPP_ORCHESTRATION_TRANSLATOR_PERMISSIONS_REFRESH,
AAPP_ORCHESTRATION_TRANSLATOR_TENANT_SWITCHED,
AAPP_MODULE
} from './consts';
export { AappAlreadyCreatedError, isAappAlreadyCreatedError } from './errors';

@ -1,11 +1,11 @@
import type { AppEventMap, AppUserIdentityChangeCause } from '$libs/aapp/events';
import {
APP_USER_IDENTITY_CAUSE_SESSION_ADOPTED,
APP_USER_IDENTITY_CAUSE_SESSION_ADOPTED_SERVER,
APP_USER_IDENTITY_CAUSE_SESSION_EXPIRED,
APP_USER_IDENTITY_CAUSE_SESSION_EXTERNAL_CHANGED,
APP_USER_IDENTITY_CAUSE_SESSION_REFRESHED,
APP_USER_IDENTITY_CAUSE_SESSION_REVOKED,
AAPP_USER_IDENTITY_CAUSE_SESSION_ADOPTED,
AAPP_USER_IDENTITY_CAUSE_SESSION_ADOPTED_SERVER,
AAPP_USER_IDENTITY_CAUSE_SESSION_EXPIRED,
AAPP_USER_IDENTITY_CAUSE_SESSION_EXTERNAL_CHANGED,
AAPP_USER_IDENTITY_CAUSE_SESSION_REFRESHED,
AAPP_USER_IDENTITY_CAUSE_SESSION_REVOKED,
publishAppUserIdentityChanged
} from '$libs/aapp/events';
import {
@ -54,11 +54,11 @@ export function publishAppIdentityFromSessionLifecycleEvent(
}
function resolveAppIdentityCause(event: SessionEvent): AppUserIdentityChangeCause | undefined {
if (event === EVENT_ADOPTED) return APP_USER_IDENTITY_CAUSE_SESSION_ADOPTED;
if (event === EVENT_ADOPTED_SERVER) return APP_USER_IDENTITY_CAUSE_SESSION_ADOPTED_SERVER;
if (event === EVENT_REFRESHED) return APP_USER_IDENTITY_CAUSE_SESSION_REFRESHED;
if (event === EVENT_REVOKED) return APP_USER_IDENTITY_CAUSE_SESSION_REVOKED;
if (event === EVENT_EXPIRED) return APP_USER_IDENTITY_CAUSE_SESSION_EXPIRED;
if (event === EVENT_EXTERNAL_CHANGED) return APP_USER_IDENTITY_CAUSE_SESSION_EXTERNAL_CHANGED;
if (event === EVENT_ADOPTED) return AAPP_USER_IDENTITY_CAUSE_SESSION_ADOPTED;
if (event === EVENT_ADOPTED_SERVER) return AAPP_USER_IDENTITY_CAUSE_SESSION_ADOPTED_SERVER;
if (event === EVENT_REFRESHED) return AAPP_USER_IDENTITY_CAUSE_SESSION_REFRESHED;
if (event === EVENT_REVOKED) return AAPP_USER_IDENTITY_CAUSE_SESSION_REVOKED;
if (event === EVENT_EXPIRED) return AAPP_USER_IDENTITY_CAUSE_SESSION_EXPIRED;
if (event === EVENT_EXTERNAL_CHANGED) return AAPP_USER_IDENTITY_CAUSE_SESSION_EXTERNAL_CHANGED;
return undefined;
}

@ -20,9 +20,9 @@ import { LogLevel, type LogEntry } from '$logr';
import type { LangNode } from '$lang';
import { MONO_LANG_CATEGORY } from '$lang/mono-lang.svelte';
import {
APP_EVENT_DISPOSE_STARTING,
APP_EVENT_USER_IDENTITY_CHANGED,
APP_USER_IDENTITY_CAUSE_SESSION_REVOKED,
AAPP_EVENT_DISPOSE_STARTING,
AAPP_EVENT_USER_IDENTITY_CHANGED,
AAPP_USER_IDENTITY_CAUSE_SESSION_REVOKED,
publishAppUserIdentityChanged
} from '$libs/aapp/events';
import { CONN_STATE_CLOSED, CONN_STATE_OPEN, createMockTransport } from '$conn';
@ -634,12 +634,12 @@ describe('createActiveApp — composition', () => {
}
});
let sizeSeenDuringDispose = -1;
App.Bus.on(APP_EVENT_DISPOSE_STARTING, () => {
App.Bus.on(AAPP_EVENT_DISPOSE_STARTING, () => {
publishAppUserIdentityChanged(App.Bus, {
event: EVENT_REVOKED,
generation: 1,
identity: { from: 'identified', to: 'none' },
cause: APP_USER_IDENTITY_CAUSE_SESSION_REVOKED
cause: AAPP_USER_IDENTITY_CAUSE_SESSION_REVOKED
});
sizeSeenDuringDispose = Permissions.size;
});
@ -657,7 +657,7 @@ describe('createActiveApp — composition', () => {
logger: { level: LogLevel.NONE, transports: [] }
});
let disposeStartingCount = 0;
App.Bus.on(APP_EVENT_DISPOSE_STARTING, () => {
App.Bus.on(AAPP_EVENT_DISPOSE_STARTING, () => {
disposeStartingCount += 1;
});
const Connections = App.createActiveConnections();
@ -688,7 +688,7 @@ describe('createActiveApp — composition', () => {
event: EVENT_REVOKED,
generation: 1,
identity: { from: 'identified', to: 'none' },
cause: APP_USER_IDENTITY_CAUSE_SESSION_REVOKED
cause: AAPP_USER_IDENTITY_CAUSE_SESSION_REVOKED
})
).toThrow();
} finally {
@ -714,14 +714,14 @@ describe('createActiveApp — composition', () => {
endpoint: 'https://active.test/permissions',
autoInvalidateOn: PERM_AUTO_INVALIDATE_STANDARD
});
App.Bus.on(APP_EVENT_DISPOSE_STARTING, () => {
App.Bus.on(AAPP_EVENT_DISPOSE_STARTING, () => {
void Promise.resolve().then(() => {
try {
publishAppUserIdentityChanged(App.Bus, {
event: EVENT_REVOKED,
generation: 2,
identity: { from: 'identified', to: 'none' },
cause: APP_USER_IDENTITY_CAUSE_SESSION_REVOKED
cause: AAPP_USER_IDENTITY_CAUSE_SESSION_REVOKED
});
} catch (error) {
deferredPublishError = error;
@ -782,7 +782,7 @@ describe('createActiveApp — composition', () => {
logger: { level: LogLevel.NONE, transports: [] }
});
const appIdentityEvents: unknown[] = [];
const off = App.Bus.on(APP_EVENT_USER_IDENTITY_CHANGED, (event) => {
const off = App.Bus.on(AAPP_EVENT_USER_IDENTITY_CHANGED, (event) => {
appIdentityEvents.push(event.payload);
});
const Connections = App.createActiveConnections();

@ -55,9 +55,9 @@ import { createEnginePermissions, createPermissionHttpHandlers } from '$svrs/per
import { createMemoryAdapter } from '$stor';
import { EVENT_ADOPTED } from '$sess/consts';
import {
APP_EVENT_USER_IDENTITY_CHANGED,
APP_USER_IDENTITY_CAUSE_SESSION_ADOPTED,
APP_USER_IDENTITY_CAUSE_SESSION_REVOKED,
AAPP_EVENT_USER_IDENTITY_CHANGED,
AAPP_USER_IDENTITY_CAUSE_SESSION_ADOPTED,
AAPP_USER_IDENTITY_CAUSE_SESSION_REVOKED,
onAppPermissionsRefreshRequested,
publishAppPermissionsRefreshRequested,
publishAppTenantSwitched,
@ -450,7 +450,7 @@ describe('ActiveApp — total ecosystem integration', () => {
}
});
const appIdentityEvents: unknown[] = [];
const offAppIdentity = App.Bus.on(APP_EVENT_USER_IDENTITY_CHANGED, (event) => {
const offAppIdentity = App.Bus.on(AAPP_EVENT_USER_IDENTITY_CHANGED, (event) => {
appIdentityEvents.push(event.payload);
});
@ -530,7 +530,7 @@ describe('ActiveApp — total ecosystem integration', () => {
event: EVENT_REVOKED,
generation: 3,
identity: { from: 'identified', to: 'none' },
cause: APP_USER_IDENTITY_CAUSE_SESSION_REVOKED
cause: AAPP_USER_IDENTITY_CAUSE_SESSION_REVOKED
});
await drainMicrotasks();
@ -635,7 +635,7 @@ describe('ActiveApp — total ecosystem integration', () => {
sessionEvents.push(event.payload);
});
const appIdentityEvents: unknown[] = [];
const offAppIdentityEvents = App.Bus.on(APP_EVENT_USER_IDENTITY_CHANGED, (event) => {
const offAppIdentityEvents = App.Bus.on(AAPP_EVENT_USER_IDENTITY_CHANGED, (event) => {
appIdentityEvents.push(event.payload);
});
@ -653,7 +653,7 @@ describe('ActiveApp — total ecosystem integration', () => {
expect(appIdentityEvents).toHaveLength(1);
expect(appIdentityEvents[0]).toMatchObject({
event: EVENT_ADOPTED,
cause: APP_USER_IDENTITY_CAUSE_SESSION_ADOPTED
cause: AAPP_USER_IDENTITY_CAUSE_SESSION_ADOPTED
});
expect(JSON.stringify(appIdentityEvents[0])).not.toContain(TOKEN_ADA);
@ -745,7 +745,7 @@ describe('ActiveApp — total ecosystem integration', () => {
expect(appIdentityEvents).toHaveLength(2);
expect(appIdentityEvents[1]).toMatchObject({
event: EVENT_ADOPTED,
cause: APP_USER_IDENTITY_CAUSE_SESSION_ADOPTED
cause: AAPP_USER_IDENTITY_CAUSE_SESSION_ADOPTED
});
expect(JSON.stringify(appIdentityEvents[1])).not.toContain(TOKEN_ADA);
expect(JSON.stringify(appIdentityEvents[1])).not.toContain(TOKEN_LINUS);
@ -793,7 +793,7 @@ describe('ActiveApp — total ecosystem integration', () => {
expect(appIdentityEvents).toHaveLength(3);
expect(appIdentityEvents[2]).toMatchObject({
event: EVENT_REVOKED,
cause: APP_USER_IDENTITY_CAUSE_SESSION_REVOKED
cause: AAPP_USER_IDENTITY_CAUSE_SESSION_REVOKED
});
expect(JSON.stringify(appIdentityEvents[2])).not.toContain(TOKEN_ADA);
expect(JSON.stringify(appIdentityEvents[2])).not.toContain(TOKEN_LINUS);
@ -915,7 +915,7 @@ describe('ActiveApp — total ecosystem integration', () => {
}
});
const appIdentityEvents: unknown[] = [];
const offAppIdentityEvents = App.Bus.on(APP_EVENT_USER_IDENTITY_CHANGED, (event) => {
const offAppIdentityEvents = App.Bus.on(AAPP_EVENT_USER_IDENTITY_CHANGED, (event) => {
appIdentityEvents.push(event.payload);
});
@ -994,7 +994,7 @@ describe('ActiveApp — total ecosystem integration', () => {
expect(appIdentityEvents).toHaveLength(1);
expect(appIdentityEvents[0]).toMatchObject({
event: EVENT_ADOPTED,
cause: APP_USER_IDENTITY_CAUSE_SESSION_ADOPTED
cause: AAPP_USER_IDENTITY_CAUSE_SESSION_ADOPTED
});
expect(JSON.stringify(appIdentityEvents[0])).not.toContain(TOKEN_ADA);
@ -1040,7 +1040,7 @@ describe('ActiveApp — total ecosystem integration', () => {
expect(appIdentityEvents).toHaveLength(2);
expect(appIdentityEvents[1]).toMatchObject({
event: EVENT_ADOPTED,
cause: APP_USER_IDENTITY_CAUSE_SESSION_ADOPTED
cause: AAPP_USER_IDENTITY_CAUSE_SESSION_ADOPTED
});
expect(JSON.stringify(appIdentityEvents[1])).not.toContain(TOKEN_ADA);
expect(JSON.stringify(appIdentityEvents[1])).not.toContain(TOKEN_LINUS);
@ -1085,7 +1085,7 @@ describe('ActiveApp — total ecosystem integration', () => {
expect(appIdentityEvents).toHaveLength(3);
expect(appIdentityEvents[2]).toMatchObject({
event: EVENT_REVOKED,
cause: APP_USER_IDENTITY_CAUSE_SESSION_REVOKED
cause: AAPP_USER_IDENTITY_CAUSE_SESSION_REVOKED
});
expect(JSON.stringify(appIdentityEvents[2])).not.toContain(TOKEN_ADA);
expect(JSON.stringify(appIdentityEvents[2])).not.toContain(TOKEN_LINUS);
@ -1878,7 +1878,7 @@ describe('ActiveApp — total ecosystem integration', () => {
}
}
});
const offAppIdentityEvents = App.Bus.on(APP_EVENT_USER_IDENTITY_CHANGED, (event) => {
const offAppIdentityEvents = App.Bus.on(AAPP_EVENT_USER_IDENTITY_CHANGED, (event) => {
appIdentityEvents.push(event.payload);
});
let offChatWebhook: (() => void) | undefined;
@ -1979,7 +1979,7 @@ describe('ActiveApp — total ecosystem integration', () => {
expect(appIdentityEvents).toHaveLength(2);
expect(appIdentityEvents[1]).toMatchObject({
event: EVENT_REVOKED,
cause: APP_USER_IDENTITY_CAUSE_SESSION_REVOKED
cause: AAPP_USER_IDENTITY_CAUSE_SESSION_REVOKED
});
expect(JSON.stringify(appIdentityEvents[1])).not.toContain(TOKEN_ADA);
expect(transport.sentMessages()).toHaveLength(1);

@ -1,8 +1,8 @@
import { describe, expect, it } from 'vitest';
import { createEngineBus } from '$buss';
import {
APP_EVENT_USER_IDENTITY_CHANGED,
APP_USER_IDENTITY_CAUSE_SESSION_ADOPTED,
AAPP_EVENT_USER_IDENTITY_CHANGED,
AAPP_USER_IDENTITY_CAUSE_SESSION_ADOPTED,
type AppEventMap
} from '$libs/aapp/events';
import { EVENT_ADOPTED } from '$sess/consts';
@ -13,7 +13,7 @@ describe('aapp session translator', () => {
it('maps session lifecycle payloads explicitly without leaking extra sensitive fields', () => {
const Bus = createEngineBus<AppEventMap & SessEventMap>();
const appPayloads: unknown[] = [];
const off = Bus.on(APP_EVENT_USER_IDENTITY_CHANGED, (event) => {
const off = Bus.on(AAPP_EVENT_USER_IDENTITY_CHANGED, (event) => {
appPayloads.push(event.payload);
});
@ -34,7 +34,7 @@ describe('aapp session translator', () => {
event: EVENT_ADOPTED,
generation: 1,
identity: { from: 'none', to: 'identified' },
cause: APP_USER_IDENTITY_CAUSE_SESSION_ADOPTED
cause: AAPP_USER_IDENTITY_CAUSE_SESSION_ADOPTED
});
off.unsubscribe();

@ -17,13 +17,13 @@ import type { ActiveStorage, SyncStorageAdapter } from '$stor';
import type { ActiveTimers } from '$timr';
import type { EngineTimersOptions } from '$libs/timers';
import type {
APP_ORCHESTRATION_SILENT,
APP_ORCHESTRATION_STANDARD,
APP_ORCHESTRATION_TRANSLATOR_CONNECTIVITY,
APP_ORCHESTRATION_TRANSLATOR_DISPOSE,
APP_ORCHESTRATION_TRANSLATOR_IDENTITY,
APP_ORCHESTRATION_TRANSLATOR_PERMISSIONS_REFRESH,
APP_ORCHESTRATION_TRANSLATOR_TENANT_SWITCHED
AAPP_ORCHESTRATION_SILENT,
AAPP_ORCHESTRATION_STANDARD,
AAPP_ORCHESTRATION_TRANSLATOR_CONNECTIVITY,
AAPP_ORCHESTRATION_TRANSLATOR_DISPOSE,
AAPP_ORCHESTRATION_TRANSLATOR_IDENTITY,
AAPP_ORCHESTRATION_TRANSLATOR_PERMISSIONS_REFRESH,
AAPP_ORCHESTRATION_TRANSLATOR_TENANT_SWITCHED
} from './consts.ts';
/** Frontend preferences eligible for App-managed persistence. */
@ -73,15 +73,15 @@ export interface ActiveAppStorageOptions {
export type ActiveAppOrchestrationPreset =
| false
| typeof APP_ORCHESTRATION_SILENT
| typeof APP_ORCHESTRATION_STANDARD;
| typeof AAPP_ORCHESTRATION_SILENT
| typeof AAPP_ORCHESTRATION_STANDARD;
export type ActiveAppOrchestrationTranslator =
| typeof APP_ORCHESTRATION_TRANSLATOR_IDENTITY
| typeof APP_ORCHESTRATION_TRANSLATOR_PERMISSIONS_REFRESH
| typeof APP_ORCHESTRATION_TRANSLATOR_TENANT_SWITCHED
| typeof APP_ORCHESTRATION_TRANSLATOR_CONNECTIVITY
| typeof APP_ORCHESTRATION_TRANSLATOR_DISPOSE;
| typeof AAPP_ORCHESTRATION_TRANSLATOR_IDENTITY
| typeof AAPP_ORCHESTRATION_TRANSLATOR_PERMISSIONS_REFRESH
| typeof AAPP_ORCHESTRATION_TRANSLATOR_TENANT_SWITCHED
| typeof AAPP_ORCHESTRATION_TRANSLATOR_CONNECTIVITY
| typeof AAPP_ORCHESTRATION_TRANSLATOR_DISPOSE;
export type ActiveAppOrchestrationOptions =
| ActiveAppOrchestrationPreset

@ -1,7 +1,7 @@
import type { BusSubscription } from '$libs/buss';
import {
APP_EVENT_TENANT_SWITCHED,
APP_EVENT_USER_IDENTITY_CHANGED
AAPP_EVENT_TENANT_SWITCHED,
AAPP_EVENT_USER_IDENTITY_CHANGED
} from '$libs/aapp/events';
import { CACH_EVENT_ALL, type CacheClock, type CacheEvent } from '$libs/cach';
import { createEngineCache } from '$svrs/cach';
@ -208,7 +208,7 @@ export function createActiveCache(options: ActiveCacheOptions = {}): ActiveCache
const subscriptions: BusSubscription[] = [];
if (targets.has(CACH_AUTO_INVALIDATE_USER_IDENTITY_CHANGE)) {
subscriptions.push(
bus.on(APP_EVENT_USER_IDENTITY_CHANGED, () => {
bus.on(AAPP_EVENT_USER_IDENTITY_CHANGED, () => {
if (disposed) return;
void track(CACH_METHOD_CLEAR, () => engine.clear()).catch(() => undefined);
})
@ -216,7 +216,7 @@ export function createActiveCache(options: ActiveCacheOptions = {}): ActiveCache
}
if (targets.has(CACH_AUTO_INVALIDATE_TENANT_SWITCHED)) {
subscriptions.push(
bus.on(APP_EVENT_TENANT_SWITCHED, () => {
bus.on(AAPP_EVENT_TENANT_SWITCHED, () => {
if (disposed) return;
void track(CACH_METHOD_CLEAR, () => engine.clear()).catch(() => undefined);
})

@ -1,5 +1,5 @@
import {
APP_EVENT_USER_IDENTITY_CHANGED,
AAPP_EVENT_USER_IDENTITY_CHANGED,
type AppEventBus
} from '$libs/aapp/events';
import type { ConnectionSessionSource } from './types.ts';
@ -7,7 +7,7 @@ import type { ConnectionSessionSource } from './types.ts';
export function createBusSessionSource(bus: AppEventBus): ConnectionSessionSource {
return {
onChange(listener) {
const subscription = bus.on(APP_EVENT_USER_IDENTITY_CHANGED, (event) => {
const subscription = bus.on(AAPP_EVENT_USER_IDENTITY_CHANGED, (event) => {
listener(event.payload);
});
return () => {

@ -22,7 +22,7 @@ import {
createEngineBus
} from '$buss';
import {
APP_USER_IDENTITY_CAUSE_SESSION_REVOKED,
AAPP_USER_IDENTITY_CAUSE_SESSION_REVOKED,
publishAppUserIdentityChanged,
type AppEventMap
} from '$libs/aapp/events';
@ -424,7 +424,7 @@ describe('Connection session bridge', () => {
event: SESS_EVENT_REVOKED,
generation: 1,
identity: { from: 'identified', to: 'none' },
cause: APP_USER_IDENTITY_CAUSE_SESSION_REVOKED
cause: AAPP_USER_IDENTITY_CAUSE_SESSION_REVOKED
});
expect(Main.state).toBe(CONN_STATE_CLOSED);

@ -1,8 +1,8 @@
import type { BusSubscription } from '$libs/buss';
import {
APP_EVENT_PERMISSIONS_REFRESH_REQUESTED,
APP_EVENT_TENANT_SWITCHED,
APP_EVENT_USER_IDENTITY_CHANGED
AAPP_EVENT_PERMISSIONS_REFRESH_REQUESTED,
AAPP_EVENT_TENANT_SWITCHED,
AAPP_EVENT_USER_IDENTITY_CHANGED
} from '$libs/aapp/events';
import { createPermissionClient } from './client.ts';
import {
@ -145,21 +145,21 @@ export function createActivePermissions(options: ActivePermissionsOptions): Acti
const subscriptions: BusSubscription[] = [];
if (targets.has(PERM_AUTO_INVALIDATE_USER_IDENTITY_CHANGE)) {
subscriptions.push(
bus.on(APP_EVENT_USER_IDENTITY_CHANGED, () => {
bus.on(AAPP_EVENT_USER_IDENTITY_CHANGED, () => {
if (!disposed) client.invalidate();
})
);
}
if (targets.has(PERM_AUTO_INVALIDATE_PERMISSIONS_REFRESH)) {
subscriptions.push(
bus.on(APP_EVENT_PERMISSIONS_REFRESH_REQUESTED, () => {
bus.on(AAPP_EVENT_PERMISSIONS_REFRESH_REQUESTED, () => {
if (!disposed) client.invalidate();
})
);
}
if (targets.has(PERM_AUTO_INVALIDATE_TENANT_SWITCHED)) {
subscriptions.push(
bus.on(APP_EVENT_TENANT_SWITCHED, () => {
bus.on(AAPP_EVENT_TENANT_SWITCHED, () => {
if (!disposed) client.invalidate();
})
);

@ -15,16 +15,16 @@ import {
AappUnsafeEventPayloadError
} from './errors.ts';
export const APP_EVENT_USER_IDENTITY_CHANGED = 'app.user.identity.changed';
export const APP_EVENT_TENANT_SWITCHED = 'app.tenant.switched';
export const APP_EVENT_PERMISSIONS_REFRESH_REQUESTED =
'app.permissions.refresh.requested';
export const APP_EVENT_CONNECTIVITY_CHANGED = 'app.connectivity.changed';
export const APP_EVENT_CACHE_INVALIDATE_REQUESTED = 'app.cache.invalidate.requested';
export const APP_EVENT_DISPOSE_STARTING = 'app.dispose.starting';
export const AAPP_EVENT_USER_IDENTITY_CHANGED = 'aapp.user.identity.changed';
export const AAPP_EVENT_TENANT_SWITCHED = 'aapp.tenant.switched';
export const AAPP_EVENT_PERMISSIONS_REFRESH_REQUESTED =
'aapp.permissions.refresh.requested';
export const AAPP_EVENT_CONNECTIVITY_CHANGED = 'aapp.connectivity.changed';
export const AAPP_EVENT_CACHE_INVALIDATE_REQUESTED = 'aapp.cache.invalidate.requested';
export const AAPP_EVENT_DISPOSE_STARTING = 'aapp.dispose.starting';
/**
* Where each `APP_EVENT_*` is allowed to fire. `'both'` is the default;
* Where each `AAPP_EVENT_*` is allowed to fire. `'both'` is the default;
* `'client'` is reserved for facts that only exist in the browser
* (connectivity is the canonical example). `assertEventCanFire` reads
* this table.
@ -33,19 +33,19 @@ export type AppEventRuntime =
| typeof AAPP_EVENT_RUNTIME_BOTH
| typeof AAPP_EVENT_RUNTIME_CLIENT;
export const APP_EVENT_RUNTIMES: Readonly<Record<string, AppEventRuntime>> = {
[APP_EVENT_USER_IDENTITY_CHANGED]: AAPP_EVENT_RUNTIME_BOTH,
[APP_EVENT_TENANT_SWITCHED]: AAPP_EVENT_RUNTIME_BOTH,
[APP_EVENT_PERMISSIONS_REFRESH_REQUESTED]: AAPP_EVENT_RUNTIME_BOTH,
[APP_EVENT_CONNECTIVITY_CHANGED]: AAPP_EVENT_RUNTIME_CLIENT,
[APP_EVENT_CACHE_INVALIDATE_REQUESTED]: AAPP_EVENT_RUNTIME_BOTH,
[APP_EVENT_DISPOSE_STARTING]: AAPP_EVENT_RUNTIME_BOTH
export const AAPP_EVENT_RUNTIMES: Readonly<Record<string, AppEventRuntime>> = {
[AAPP_EVENT_USER_IDENTITY_CHANGED]: AAPP_EVENT_RUNTIME_BOTH,
[AAPP_EVENT_TENANT_SWITCHED]: AAPP_EVENT_RUNTIME_BOTH,
[AAPP_EVENT_PERMISSIONS_REFRESH_REQUESTED]: AAPP_EVENT_RUNTIME_BOTH,
[AAPP_EVENT_CONNECTIVITY_CHANGED]: AAPP_EVENT_RUNTIME_CLIENT,
[AAPP_EVENT_CACHE_INVALIDATE_REQUESTED]: AAPP_EVENT_RUNTIME_BOTH,
[AAPP_EVENT_DISPOSE_STARTING]: AAPP_EVENT_RUNTIME_BOTH
};
/**
* Throws `AappInvalidEventRuntimeError` if `type` is an `APP_EVENT_*`
* Throws `AappInvalidEventRuntimeError` if `type` is an `AAPP_EVENT_*`
* declared as client-only and the current runtime is the server (or
* vice-versa). Module events are not registered in `APP_EVENT_RUNTIMES`
* vice-versa). Module events are not registered in `AAPP_EVENT_RUNTIMES`
* and are accepted unconditionally — only the public app-event surface
* is gated.
*/
@ -53,7 +53,7 @@ export function assertEventCanFire(
type: string,
where: typeof AAPP_EVENT_RUNTIME_CLIENT | 'server'
): void {
const allowed = APP_EVENT_RUNTIMES[type];
const allowed = AAPP_EVENT_RUNTIMES[type];
if (allowed === undefined) return;
if (allowed === AAPP_EVENT_RUNTIME_BOTH) return;
if (allowed === where) return;
@ -88,21 +88,21 @@ function isSensitivePayloadKey(key: string): boolean {
return AAPP_EVENT_SENSITIVE_KEY_PARTS.some((part) => normalized.includes(part));
}
export const APP_USER_IDENTITY_CAUSE_SESSION_ADOPTED = 'session-adopted';
export const APP_USER_IDENTITY_CAUSE_SESSION_ADOPTED_SERVER = 'session-adopted-server';
export const APP_USER_IDENTITY_CAUSE_SESSION_REFRESHED = 'session-refreshed';
export const APP_USER_IDENTITY_CAUSE_SESSION_REVOKED = 'session-revoked';
export const APP_USER_IDENTITY_CAUSE_SESSION_EXPIRED = 'session-expired';
export const APP_USER_IDENTITY_CAUSE_SESSION_EXTERNAL_CHANGED =
export const AAPP_USER_IDENTITY_CAUSE_SESSION_ADOPTED = 'session-adopted';
export const AAPP_USER_IDENTITY_CAUSE_SESSION_ADOPTED_SERVER = 'session-adopted-server';
export const AAPP_USER_IDENTITY_CAUSE_SESSION_REFRESHED = 'session-refreshed';
export const AAPP_USER_IDENTITY_CAUSE_SESSION_REVOKED = 'session-revoked';
export const AAPP_USER_IDENTITY_CAUSE_SESSION_EXPIRED = 'session-expired';
export const AAPP_USER_IDENTITY_CAUSE_SESSION_EXTERNAL_CHANGED =
'session-external-changed';
export type AppUserIdentityChangeCause =
| typeof APP_USER_IDENTITY_CAUSE_SESSION_ADOPTED
| typeof APP_USER_IDENTITY_CAUSE_SESSION_ADOPTED_SERVER
| typeof APP_USER_IDENTITY_CAUSE_SESSION_REFRESHED
| typeof APP_USER_IDENTITY_CAUSE_SESSION_REVOKED
| typeof APP_USER_IDENTITY_CAUSE_SESSION_EXPIRED
| typeof APP_USER_IDENTITY_CAUSE_SESSION_EXTERNAL_CHANGED;
| typeof AAPP_USER_IDENTITY_CAUSE_SESSION_ADOPTED
| typeof AAPP_USER_IDENTITY_CAUSE_SESSION_ADOPTED_SERVER
| typeof AAPP_USER_IDENTITY_CAUSE_SESSION_REFRESHED
| typeof AAPP_USER_IDENTITY_CAUSE_SESSION_REVOKED
| typeof AAPP_USER_IDENTITY_CAUSE_SESSION_EXPIRED
| typeof AAPP_USER_IDENTITY_CAUSE_SESSION_EXTERNAL_CHANGED;
export interface AppUserIdentityChangedPayload {
readonly event: string;
@ -143,12 +143,12 @@ export interface AppDisposeStartingPayload {
}
export interface AppEventMap {
[APP_EVENT_USER_IDENTITY_CHANGED]: AppUserIdentityChangedPayload;
[APP_EVENT_TENANT_SWITCHED]: AppTenantSwitchedPayload;
[APP_EVENT_PERMISSIONS_REFRESH_REQUESTED]: AppPermissionsRefreshRequestedPayload;
[APP_EVENT_CONNECTIVITY_CHANGED]: AppConnectivityChangedPayload;
[APP_EVENT_CACHE_INVALIDATE_REQUESTED]: AppCacheInvalidateRequestedPayload;
[APP_EVENT_DISPOSE_STARTING]: AppDisposeStartingPayload;
[AAPP_EVENT_USER_IDENTITY_CHANGED]: AppUserIdentityChangedPayload;
[AAPP_EVENT_TENANT_SWITCHED]: AppTenantSwitchedPayload;
[AAPP_EVENT_PERMISSIONS_REFRESH_REQUESTED]: AppPermissionsRefreshRequestedPayload;
[AAPP_EVENT_CONNECTIVITY_CHANGED]: AppConnectivityChangedPayload;
[AAPP_EVENT_CACHE_INVALIDATE_REQUESTED]: AppCacheInvalidateRequestedPayload;
[AAPP_EVENT_DISPOSE_STARTING]: AppDisposeStartingPayload;
}
export type AppEventBus = Pick<EngineBus<AppEventMap>, 'on' | 'once'>;
@ -162,9 +162,9 @@ export function publishAppUserIdentityChanged(
payload: AppUserIdentityChangedPayload,
options?: BusPublishOptions
) {
assertEventCanFire(APP_EVENT_USER_IDENTITY_CHANGED, currentRuntime());
assertAppEventPayloadSafe(APP_EVENT_USER_IDENTITY_CHANGED, payload);
return bus.publish(APP_EVENT_USER_IDENTITY_CHANGED, payload, options);
assertEventCanFire(AAPP_EVENT_USER_IDENTITY_CHANGED, currentRuntime());
assertAppEventPayloadSafe(AAPP_EVENT_USER_IDENTITY_CHANGED, payload);
return bus.publish(AAPP_EVENT_USER_IDENTITY_CHANGED, payload, options);
}
export function publishAppPermissionsRefreshRequested(
@ -172,9 +172,9 @@ export function publishAppPermissionsRefreshRequested(
payload: AppPermissionsRefreshRequestedPayload,
options?: BusPublishOptions
) {
assertEventCanFire(APP_EVENT_PERMISSIONS_REFRESH_REQUESTED, currentRuntime());
assertAppEventPayloadSafe(APP_EVENT_PERMISSIONS_REFRESH_REQUESTED, payload);
return bus.publish(APP_EVENT_PERMISSIONS_REFRESH_REQUESTED, payload, options);
assertEventCanFire(AAPP_EVENT_PERMISSIONS_REFRESH_REQUESTED, currentRuntime());
assertAppEventPayloadSafe(AAPP_EVENT_PERMISSIONS_REFRESH_REQUESTED, payload);
return bus.publish(AAPP_EVENT_PERMISSIONS_REFRESH_REQUESTED, payload, options);
}
export function publishAppTenantSwitched(
@ -182,9 +182,9 @@ export function publishAppTenantSwitched(
payload: AppTenantSwitchedPayload,
options?: BusPublishOptions
) {
assertEventCanFire(APP_EVENT_TENANT_SWITCHED, currentRuntime());
assertAppEventPayloadSafe(APP_EVENT_TENANT_SWITCHED, payload);
return bus.publish(APP_EVENT_TENANT_SWITCHED, payload, options);
assertEventCanFire(AAPP_EVENT_TENANT_SWITCHED, currentRuntime());
assertAppEventPayloadSafe(AAPP_EVENT_TENANT_SWITCHED, payload);
return bus.publish(AAPP_EVENT_TENANT_SWITCHED, payload, options);
}
export function publishAppConnectivityChanged(
@ -192,9 +192,9 @@ export function publishAppConnectivityChanged(
payload: AppConnectivityChangedPayload,
options?: BusPublishOptions
) {
assertEventCanFire(APP_EVENT_CONNECTIVITY_CHANGED, currentRuntime());
assertAppEventPayloadSafe(APP_EVENT_CONNECTIVITY_CHANGED, payload);
return bus.publish(APP_EVENT_CONNECTIVITY_CHANGED, payload, options);
assertEventCanFire(AAPP_EVENT_CONNECTIVITY_CHANGED, currentRuntime());
assertAppEventPayloadSafe(AAPP_EVENT_CONNECTIVITY_CHANGED, payload);
return bus.publish(AAPP_EVENT_CONNECTIVITY_CHANGED, payload, options);
}
export function publishAppCacheInvalidateRequested(
@ -202,9 +202,9 @@ export function publishAppCacheInvalidateRequested(
payload: AppCacheInvalidateRequestedPayload,
options?: BusPublishOptions
) {
assertEventCanFire(APP_EVENT_CACHE_INVALIDATE_REQUESTED, currentRuntime());
assertAppEventPayloadSafe(APP_EVENT_CACHE_INVALIDATE_REQUESTED, payload);
return bus.publish(APP_EVENT_CACHE_INVALIDATE_REQUESTED, payload, options);
assertEventCanFire(AAPP_EVENT_CACHE_INVALIDATE_REQUESTED, currentRuntime());
assertAppEventPayloadSafe(AAPP_EVENT_CACHE_INVALIDATE_REQUESTED, payload);
return bus.publish(AAPP_EVENT_CACHE_INVALIDATE_REQUESTED, payload, options);
}
export function publishAppDisposeStarting(
@ -212,9 +212,9 @@ export function publishAppDisposeStarting(
payload: AppDisposeStartingPayload,
options?: BusPublishOptions
) {
assertEventCanFire(APP_EVENT_DISPOSE_STARTING, currentRuntime());
assertAppEventPayloadSafe(APP_EVENT_DISPOSE_STARTING, payload);
return bus.publish(APP_EVENT_DISPOSE_STARTING, payload, options);
assertEventCanFire(AAPP_EVENT_DISPOSE_STARTING, currentRuntime());
assertAppEventPayloadSafe(AAPP_EVENT_DISPOSE_STARTING, payload);
return bus.publish(AAPP_EVENT_DISPOSE_STARTING, payload, options);
}
export function onAppUserIdentityChanged(
@ -223,7 +223,7 @@ export function onAppUserIdentityChanged(
event: BusEnvelope<string, AppUserIdentityChangedPayload>
) => void | Promise<void>
): BusSubscription {
return bus.on(APP_EVENT_USER_IDENTITY_CHANGED, listener);
return bus.on(AAPP_EVENT_USER_IDENTITY_CHANGED, listener);
}
export function onAppPermissionsRefreshRequested(
@ -232,14 +232,14 @@ export function onAppPermissionsRefreshRequested(
event: BusEnvelope<string, AppPermissionsRefreshRequestedPayload>
) => void | Promise<void>
): BusSubscription {
return bus.on(APP_EVENT_PERMISSIONS_REFRESH_REQUESTED, listener);
return bus.on(AAPP_EVENT_PERMISSIONS_REFRESH_REQUESTED, listener);
}
export function onAppTenantSwitched(
bus: AppEventBus,
listener: (event: BusEnvelope<string, AppTenantSwitchedPayload>) => void | Promise<void>
): BusSubscription {
return bus.on(APP_EVENT_TENANT_SWITCHED, listener);
return bus.on(AAPP_EVENT_TENANT_SWITCHED, listener);
}
export function onAppConnectivityChanged(
@ -248,7 +248,7 @@ export function onAppConnectivityChanged(
event: BusEnvelope<string, AppConnectivityChangedPayload>
) => void | Promise<void>
): BusSubscription {
return bus.on(APP_EVENT_CONNECTIVITY_CHANGED, listener);
return bus.on(AAPP_EVENT_CONNECTIVITY_CHANGED, listener);
}
export function onAppCacheInvalidateRequested(
@ -257,12 +257,12 @@ export function onAppCacheInvalidateRequested(
event: BusEnvelope<string, AppCacheInvalidateRequestedPayload>
) => void | Promise<void>
): BusSubscription {
return bus.on(APP_EVENT_CACHE_INVALIDATE_REQUESTED, listener);
return bus.on(AAPP_EVENT_CACHE_INVALIDATE_REQUESTED, listener);
}
export function onAppDisposeStarting(
bus: AppEventBus,
listener: (event: BusEnvelope<string, AppDisposeStartingPayload>) => void | Promise<void>
): BusSubscription {
return bus.on(APP_EVENT_DISPOSE_STARTING, listener);
return bus.on(AAPP_EVENT_DISPOSE_STARTING, listener);
}

@ -1,9 +1,9 @@
import { describe, expect, it } from 'vitest';
import { createEngineBus } from '$buss';
import {
APP_EVENT_CONNECTIVITY_CHANGED,
APP_EVENT_USER_IDENTITY_CHANGED,
APP_USER_IDENTITY_CAUSE_SESSION_REVOKED,
AAPP_EVENT_CONNECTIVITY_CHANGED,
AAPP_EVENT_USER_IDENTITY_CHANGED,
AAPP_USER_IDENTITY_CAUSE_SESSION_REVOKED,
assertEventCanFire,
onAppDisposeStarting,
onAppUserIdentityChanged,
@ -32,7 +32,7 @@ describe('libs/aapp/events', () => {
event: 'REVOKED',
generation: 1,
identity: { from: 'identified', to: 'none' },
cause: APP_USER_IDENTITY_CAUSE_SESSION_REVOKED
cause: AAPP_USER_IDENTITY_CAUSE_SESSION_REVOKED
});
publishAppDisposeStarting(Bus, { cause: 'test' });
@ -41,7 +41,7 @@ describe('libs/aapp/events', () => {
event: 'REVOKED',
generation: 1,
identity: { from: 'identified', to: 'none' },
cause: APP_USER_IDENTITY_CAUSE_SESSION_REVOKED
cause: AAPP_USER_IDENTITY_CAUSE_SESSION_REVOKED
}
]);
expect(disposePayloads).toEqual([{ cause: 'test' }]);
@ -52,13 +52,13 @@ describe('libs/aapp/events', () => {
});
it('assertEventCanFire allows both-runtime events anywhere', () => {
expect(() => assertEventCanFire(APP_EVENT_USER_IDENTITY_CHANGED, 'server')).not.toThrow();
expect(() => assertEventCanFire(APP_EVENT_USER_IDENTITY_CHANGED, 'client')).not.toThrow();
expect(() => assertEventCanFire(AAPP_EVENT_USER_IDENTITY_CHANGED, 'server')).not.toThrow();
expect(() => assertEventCanFire(AAPP_EVENT_USER_IDENTITY_CHANGED, 'client')).not.toThrow();
});
it('assertEventCanFire throws when a client-only event is fired on the server', () => {
try {
assertEventCanFire(APP_EVENT_CONNECTIVITY_CHANGED, 'server');
assertEventCanFire(AAPP_EVENT_CONNECTIVITY_CHANGED, 'server');
expect.fail('expected assertion to throw');
} catch (error) {
expect(isAappInvalidEventRuntimeError(error)).toBe(true);
@ -79,7 +79,7 @@ describe('libs/aapp/events', () => {
event: 'REVOKED',
generation: 1,
identity: { from: 'identified', to: 'none' },
cause: APP_USER_IDENTITY_CAUSE_SESSION_REVOKED,
cause: AAPP_USER_IDENTITY_CAUSE_SESSION_REVOKED,
credential: { token: 'secret-token' }
} as unknown as Parameters<typeof publishAppUserIdentityChanged>[1]
);

@ -1292,7 +1292,7 @@ const artifactApis = {
{
name: 'autoReauthOn',
purpose: 'Automatic app-event reauth policy.',
notes: 'Defaults to none. standard listens to APP_EVENT_USER_IDENTITY_CHANGED.'
notes: 'Defaults to none. standard listens to AAPP_EVENT_USER_IDENTITY_CHANGED.'
},
{
name: 'session',
@ -1674,7 +1674,7 @@ const AuthClient = App.createActiveAuth({
{
name: 'publishing inline event strings',
purpose: 'Magic strings drift and break refactors.',
notes: 'Declare event constants in uppercase at the owner boundary, for example APP_EVENT_USER_IDENTITY_CHANGED.'
notes: 'Declare event constants in uppercase at the owner boundary, for example AAPP_EVENT_USER_IDENTITY_CHANGED.'
}
],
quickStart: {
@ -1744,7 +1744,7 @@ sub.unsubscribe();`
{
name: 'libs/aapp/events.ts',
purpose: 'Imports interfaces from $libs/buss.',
notes: 'Defines APP_EVENT_* constants and helpers; never touches the engine.'
notes: 'Defines AAPP_EVENT_* constants and helpers; never touches the engine.'
}
],
code: {
@ -1807,7 +1807,7 @@ export function createEngineSession(options: EngineSessionOptions) {
notes: '"auth.sign_in.succeeded", "auth.csrf.issued", "auth.password.changed", …'
},
{
name: 'APP_EVENT_*',
name: 'AAPP_EVENT_*',
purpose: 'Public app contract events.',
notes: '"app.user.identity.changed", "app.tenant.switched", …'
},
@ -1826,9 +1826,9 @@ export function createEngineSession(options: EngineSessionOptions) {
{
title: 'App.Event Contract',
body: [
'Stable public app events live in $libs/aapp/events, not inside individual artifacts. Examples are APP_EVENT_USER_IDENTITY_CHANGED, APP_EVENT_TENANT_SWITCHED, APP_EVENT_PERMISSIONS_REFRESH_REQUESTED, APP_EVENT_CONNECTIVITY_CHANGED, APP_EVENT_CACHE_INVALIDATE_REQUESTED and APP_EVENT_DISPOSE_STARTING.',
'Event constants are mandatory, and app events should normally flow through onApp* / publishApp* helpers. Those helpers keep payload typing, runtime guards and unsafe-payload checks in one place. Raw bus.on(APP_EVENT_...) is acceptable for low-level tests; raw bus.publish("app...") is not application code.',
'The string value stays lowercase scoped; the exported symbol is uppercase snake. Current built-in translators publish APP_EVENT_USER_IDENTITY_CHANGED from SESS_EVENT_CHANGED and APP_EVENT_DISPOSE_STARTING during App.dispose(). The other app events are stable contract points for explicit app code and future translators.'
'Stable public app events live in $libs/aapp/events, not inside individual artifacts. Examples are AAPP_EVENT_USER_IDENTITY_CHANGED, AAPP_EVENT_TENANT_SWITCHED, AAPP_EVENT_PERMISSIONS_REFRESH_REQUESTED, AAPP_EVENT_CONNECTIVITY_CHANGED, AAPP_EVENT_CACHE_INVALIDATE_REQUESTED and AAPP_EVENT_DISPOSE_STARTING.',
'Event constants are mandatory, and app events should normally flow through onApp* / publishApp* helpers. Those helpers keep payload typing, runtime guards and unsafe-payload checks in one place. Raw bus.on(AAPP_EVENT_...) is acceptable for low-level tests; raw bus.publish("app...") is not application code.',
'The string value stays lowercase scoped; the exported symbol is uppercase snake. Current built-in translators publish AAPP_EVENT_USER_IDENTITY_CHANGED from SESS_EVENT_CHANGED and AAPP_EVENT_DISPOSE_STARTING during App.dispose(). The other app events are stable contract points for explicit app code and future translators.'
]
},
{
@ -1873,7 +1873,7 @@ export function createEngineSession(options: EngineSessionOptions) {
{
name: 'orchestration: standard',
purpose: 'Enables the App translator.',
notes: 'Session changes can become APP_EVENT_USER_IDENTITY_CHANGED.'
notes: 'Session changes can become AAPP_EVENT_USER_IDENTITY_CHANGED.'
},
{
name: 'cache.autoInvalidateOn',
@ -1930,7 +1930,7 @@ const Chat = Connections.createConnection('chat', {
Sess.adoptServer(nextSessionFromServer);
// 1. Sess updates its current session, then publishes SESS_EVENT_CHANGED.
// 2. aapp translates that module event to APP_EVENT_USER_IDENTITY_CHANGED.
// 2. aapp translates that module event to AAPP_EVENT_USER_IDENTITY_CHANGED.
// 3. Cache invalidates because cache.autoInvalidateOn opted in.
// 4. Permissions.invalidate() runs because permissions.autoInvalidateOn opted in.
// 5. Chat calls auth(), sends a fresh conn.auth frame with the new credential,
@ -2096,7 +2096,7 @@ Sess.adoptServer(data.session);`
{
title: 'Bus Integration',
body: [
'When Session is created through App, App injects App.Bus. Session publishes safe sess.* events after state has been updated; aapp can translate SESS_EVENT_CHANGED into APP_EVENT_USER_IDENTITY_CHANGED.',
'When Session is created through App, App injects App.Bus. Session publishes safe sess.* events after state has been updated; aapp can translate SESS_EVENT_CHANGED into AAPP_EVENT_USER_IDENTITY_CHANGED.',
'Cache, Permissions and Connections do not listen to sess.* directly. They react only to public app.* events and only when their own autoInvalidateOn or autoReauthOn option opts in.'
]
}
@ -2237,7 +2237,7 @@ const decision = await Permissions.check({
title: 'App.Bus Auto Invalidation',
body: [
'ActivePermissions can subscribe to public app.* events when App injects App.Bus. The default is safe: no automatic invalidation happens unless autoInvalidateOn is configured.',
"autoInvalidateOn: 'standard' currently invalidates the local decision cache on APP_EVENT_USER_IDENTITY_CHANGED, APP_EVENT_PERMISSIONS_REFRESH_REQUESTED and APP_EVENT_TENANT_SWITCHED.",
"autoInvalidateOn: 'standard' currently invalidates the local decision cache on AAPP_EVENT_USER_IDENTITY_CHANGED, AAPP_EVENT_PERMISSIONS_REFRESH_REQUESTED and AAPP_EVENT_TENANT_SWITCHED.",
'Permissions does not listen to sess.*, auth internals or cache internals directly. The public bus contract keeps the client reflector decoupled from the source of the identity or policy change.'
],
code: {
@ -2502,7 +2502,7 @@ const Permissions = createEnginePermissions({
title: 'App.Bus Auto Invalidation',
body: [
'App injects App.Bus into App.Cache. By default Cache only observes its own cache events; it does not clear when the app publishes identity or tenant facts.',
"Set cache.autoInvalidateOn: 'standard' to clear the active cache on APP_EVENT_USER_IDENTITY_CHANGED and APP_EVENT_TENANT_SWITCHED. Use a list such as ['userIdentityChange'] for narrower behavior.",
"Set cache.autoInvalidateOn: 'standard' to clear the active cache on AAPP_EVENT_USER_IDENTITY_CHANGED and AAPP_EVENT_TENANT_SWITCHED. Use a list such as ['userIdentityChange'] for narrower behavior.",
'Cache listens only to public app.* events. It should not import sess, auth or perm internals to decide when private data becomes unsafe.'
],
code: {
@ -3915,7 +3915,7 @@ await Chat.connect();`
{
title: 'App.Bus Reauth Source',
body: [
'If autoReauthOn is enabled in the registry, Connections derives a ConnectionSessionSource from APP_EVENT_USER_IDENTITY_CHANGED. It does not listen to sess.* directly and does not import auth, perm or cache internals.',
'If autoReauthOn is enabled in the registry, Connections derives a ConnectionSessionSource from AAPP_EVENT_USER_IDENTITY_CHANGED. It does not listen to sess.* directly and does not import auth, perm or cache internals.',
'Each connection still decides whether to react through its own session option. Reauthentication additionally requires an auth provider; without auth there is no credential payload to send, so the connection can only be observed or manually handled.'
]
},

@ -46,7 +46,7 @@ const Session = App.createActiveSession({
});`;
const eventFlow = `sess emits SESS_EVENT_CHANGED
aapp translates it into APP_EVENT_USER_IDENTITY_CHANGED
aapp translates it into AAPP_EVENT_USER_IDENTITY_CHANGED
cache/permissions/connections react only when their own auto*On option opts in`;
const disposal = `import { onDestroy } from 'svelte';
@ -248,8 +248,8 @@ onDestroy(() => App.dispose());`;
<CodeBlock code={eventFlow} lang="txt" title="Identity event flow" />
<p>
<code>orchestration</code> controls translators only. Today the built-in sources are
identity (<code>SESS_EVENT_CHANGED</code> to <code>APP_EVENT_USER_IDENTITY_CHANGED</code>)
and dispose (<code>App.dispose()</code> to <code>APP_EVENT_DISPOSE_STARTING</code>).
identity (<code>SESS_EVENT_CHANGED</code> to <code>AAPP_EVENT_USER_IDENTITY_CHANGED</code>)
and dispose (<code>App.dispose()</code> to <code>AAPP_EVENT_DISPOSE_STARTING</code>).
Other public events such as tenant switch, permission refresh, connectivity and cache
invalidation are typed contracts for explicit publication or future translators.
</p>
@ -269,7 +269,7 @@ onDestroy(() => App.dispose());`;
</table>
<Callout variant="warn" title="Public payloads only">
<p>
<code>APP_EVENT_*</code> payloads are observable framework contracts. Do not put
<code>AAPP_EVENT_*</code> payloads are observable framework contracts. Do not put
tokens, passwords, authorization headers, refresh secrets or sensitive hashes in
them. Use actor ids, tenant ids, causes and correlation ids.
</p>

Loading…
Cancel
Save

Powered by TurnKey Linux.