Two new orca presets in `arts/active-app/presets/`:
- `applyConnectionsReauthOnIdentityChange` — listens to
`SESSION_EVENT_IDENTITY_CHANGED` and calls
`App.connections.reauthenticateAll()`. Closes the canonical motivating
scenario for orca: "chat connected with the previous user's
credentials" can no longer happen with this preset wired.
- `applyConnectionsCloseOnRevoke` — listens to `SESSION_EVENT_REVOKED`
and calls `App.connections.closeAll('session-revoked')`, leaving no
socket alive carrying revoked credentials.
`applyStandardOrca` now picks both up automatically when `App.connections`
is declared, and the index barrel re-exports the new shapes.
Removes the dead `autoReauthOn` config — declared on
`EngineConnectionsOptions` but never read by any runtime code:
- field removed from `connection/types.ts`
- `CONNECTION_AUTO_REAUTH_*` constants removed from `connection/consts.ts`
- `ConnectionAutoReauthOn` / `ConnectionAutoReauthTarget` types removed
- unused test import removed from `connection.test.ts`
- connection README rewritten: orca preset is now the canonical bridge,
per-connection `session: { ... }` documented as the manual / standalone
alternative
- demo route artifact-docs.ts and aapp page updated to use
`applyStandardOrca(App)` instead of `autoReauthOn: 'standard'`
The per-connection `session-wiring.ts` mechanism stays as-is — it's
useful for connections that live outside an App composition or that
need a custom `ConnectionSessionSource`. README now spells out the
two paths: orca preset for App-composed apps, per-connection `session`
for manual control.
Suite: 1482 / 1482 (+4 from this commit: 3 preset behaviour tests
+ 1 `applyStandardOrca` connection wiring test).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
master
parent
c0ed619372
commit
2473ade4ad
@ -0,0 +1,42 @@
|
|||||||
|
import { ORCA_ON_ERROR_CONTINUE, ORCA_STAGE_MAIN, orcaError, orcaSuccess } from '$orca';
|
||||||
|
import { SESSION_EVENT_REVOKED } from '$session';
|
||||||
|
import type { ActiveConnections } from '$connection/types';
|
||||||
|
import type { ActiveAppCore } from '../types.ts';
|
||||||
|
|
||||||
|
const ACTION_ID = 'connections.close-on-revoke';
|
||||||
|
const TOKEN_CLOSED = 'connections:closed-on-revoke';
|
||||||
|
const CLOSE_REASON = 'session-revoked';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shape this preset requires from `App`. Only `closeAll()` is needed.
|
||||||
|
*/
|
||||||
|
export interface ConnectionsCloseOnRevokeApp extends ActiveAppCore {
|
||||||
|
readonly connections: Pick<ActiveConnections, 'closeAll'>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers an orca action that closes every active connection when
|
||||||
|
* the session is revoked. Used together with
|
||||||
|
* `applyCacheClearOnRevoke` to ensure that a logout / forced sign-out
|
||||||
|
* leaves no live socket carrying the revoked identity's credentials.
|
||||||
|
*
|
||||||
|
* Returns a detach function. Calling it unregisters the action.
|
||||||
|
*/
|
||||||
|
export function applyConnectionsCloseOnRevoke(
|
||||||
|
App: ConnectionsCloseOnRevokeApp
|
||||||
|
): () => void {
|
||||||
|
return App.Orca.onEvent(SESSION_EVENT_REVOKED, {
|
||||||
|
id: ACTION_ID,
|
||||||
|
stage: ORCA_STAGE_MAIN,
|
||||||
|
provides: [TOKEN_CLOSED],
|
||||||
|
onError: ORCA_ON_ERROR_CONTINUE,
|
||||||
|
action: async () => {
|
||||||
|
try {
|
||||||
|
App.connections.closeAll(CLOSE_REASON);
|
||||||
|
return orcaSuccess({ emits: [TOKEN_CLOSED] });
|
||||||
|
} catch (error) {
|
||||||
|
return orcaError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
@ -0,0 +1,47 @@
|
|||||||
|
import { ORCA_ON_ERROR_CONTINUE, ORCA_STAGE_MAIN, orcaError, orcaSuccess } from '$orca';
|
||||||
|
import { SESSION_EVENT_IDENTITY_CHANGED } from '$session';
|
||||||
|
import type { ActiveConnections } from '$connection/types';
|
||||||
|
import type { ActiveAppCore } from '../types.ts';
|
||||||
|
|
||||||
|
const ACTION_ID = 'connections.reauth-on-identity-change';
|
||||||
|
const TOKEN_REAUTHENTICATED = 'connections:reauthenticated-on-identity';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shape this preset requires from `App`. Only the
|
||||||
|
* `reauthenticateAll()` method is actually invoked, so apps can
|
||||||
|
* inject any compatible adapter — no need to expose the full
|
||||||
|
* `ActiveConnections` surface.
|
||||||
|
*/
|
||||||
|
export interface ConnectionsReauthOnIdentityChangeApp extends ActiveAppCore {
|
||||||
|
readonly connections: Pick<ActiveConnections, 'reauthenticateAll'>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers an orca action that asks every active connection to
|
||||||
|
* reauthenticate when the session's actor identity changes. Pairs with
|
||||||
|
* `applyCacheClearOnIdentityChange` and
|
||||||
|
* `applyPermInvalidateOnIdentityChange` to flush stale state from the
|
||||||
|
* previous user before any new request flies — the canonical motivator
|
||||||
|
* scenario for orca: "chat connected with the previous user's
|
||||||
|
* credentials" can no longer happen with this preset registered.
|
||||||
|
*
|
||||||
|
* Returns a detach function. Calling it unregisters the action.
|
||||||
|
*/
|
||||||
|
export function applyConnectionsReauthOnIdentityChange(
|
||||||
|
App: ConnectionsReauthOnIdentityChangeApp
|
||||||
|
): () => void {
|
||||||
|
return App.Orca.onEvent(SESSION_EVENT_IDENTITY_CHANGED, {
|
||||||
|
id: ACTION_ID,
|
||||||
|
stage: ORCA_STAGE_MAIN,
|
||||||
|
provides: [TOKEN_REAUTHENTICATED],
|
||||||
|
onError: ORCA_ON_ERROR_CONTINUE,
|
||||||
|
action: async () => {
|
||||||
|
try {
|
||||||
|
await App.connections.reauthenticateAll();
|
||||||
|
return orcaSuccess({ emits: [TOKEN_REAUTHENTICATED] });
|
||||||
|
} catch (error) {
|
||||||
|
return orcaError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
Loading…
Reference in new issue