Extract session revoke resolution

master
dev 5 months ago
parent af681f8b25
commit 926c640c6f

@ -18,6 +18,7 @@ Estado al cierre:
- `arts/stor/engine-storage.ts` delega el registro de defaults conflictivos en `defaults-registry.ts`.
- `arts/sess/engine-session.ts` delega la clasificacion `none/anonymous/identified` en `session-identity.ts`.
- `arts/sess/engine-session.ts` delega snapshot, generation, dispatch, persistencia y commits en `session-state.ts`.
- `arts/sess/engine-session.ts` delega la resolucion de revoke local/global/degradado en `session-revoke.ts`.
- Integracion total ampliada: `Auth.signOut()` valida anonimizacion, invalidacion de `Permissions` y evento `Cache.invalidate`.
- Tanda focalizada verde: `npx vitest run src/arts/conn src/libs/cach src/arts/cach src/svrs/cach src/arts/auth src/svrs/auth src/libs/auth src/arts/aapp/test/ecosystem.integration.test.ts` -> 19 archivos, 82 tests.
- `/test/ecosystem` revisado en navegador: carga sin errores de consola, `ar` cambia a `rtl`, Formats se actualiza por locale, Perm cambia con rol `viewer`, Cach re-scopea por locale y Conn loopback publica/recibe.

@ -21,11 +21,7 @@ import {
REFRESH_STATUS_FAILED,
REFRESH_STATUS_REFRESHED,
REFRESH_STATUS_SKIPPED,
REVOKE_REASON_MISSING_REVOKE_URL,
REVOKE_REASON_NETWORK_ERROR,
REVOKE_REASON_NO_SESSION,
REVOKE_REASON_SERVER_REJECTED,
REVOKE_SCOPE_GLOBAL,
REVOKE_SCOPE_LOCAL,
SESSION_DIAGNOSTIC_EVENTS,
SKIP_REASON_NO_REFRESH_FN,
@ -41,6 +37,7 @@ import {
readField,
toError
} from './session-helpers.ts';
import { resolveSessionRevoke } from './session-revoke.ts';
import {
createSessionBroadcastSync,
hydrateSessionStorage,
@ -312,78 +309,14 @@ export function createEngineSession<TUser, TCredential = undefined, TData = unde
ensureLive(ENGINE_METHOD_REVOKE);
const current = state.current;
if (current === null) {
return {
localRevoked: true,
globalRevoked: false,
scope: REVOKE_SCOPE_LOCAL,
reason: REVOKE_REASON_NO_SESSION
};
}
// Default to global when an `onRevoke` handler is configured —
// cookie-auth apps almost always want the server-side cookie
// cleared along with the local snapshot.
const requestedScope =
opts.scope ?? (onRevoke !== undefined ? REVOKE_SCOPE_GLOBAL : REVOKE_SCOPE_LOCAL);
let result: RevokeResult;
if (requestedScope === REVOKE_SCOPE_GLOBAL) {
if (onRevoke === undefined) {
result = {
localRevoked: true,
globalRevoked: false,
scope: REVOKE_SCOPE_LOCAL,
reason: REVOKE_REASON_MISSING_REVOKE_URL
};
emitSessionDiagnostic(diagnostics, SESSION_DIAGNOSTIC_EVENTS.REVOKE_GLOBAL_NO_HANDLER, {
error: REVOKE_REASON_MISSING_REVOKE_URL
});
} else {
try {
const ok = await onRevoke(current, { logger });
if (ok) {
result = {
localRevoked: true,
globalRevoked: true,
scope: REVOKE_SCOPE_GLOBAL
};
} else {
result = {
localRevoked: true,
globalRevoked: false,
scope: REVOKE_SCOPE_LOCAL,
reason: REVOKE_REASON_SERVER_REJECTED
};
emitSessionDiagnostic(
diagnostics,
SESSION_DIAGNOSTIC_EVENTS.REVOKE_GLOBAL_SERVER_REJECTED,
{ error: REVOKE_REASON_SERVER_REJECTED }
);
}
} catch (err) {
result = {
localRevoked: true,
globalRevoked: false,
scope: REVOKE_SCOPE_LOCAL,
reason: REVOKE_REASON_NETWORK_ERROR
};
emitSessionDiagnostic(
diagnostics,
SESSION_DIAGNOSTIC_EVENTS.REVOKE_GLOBAL_HANDLER_FAILED,
{ error: toError(err) }
);
}
}
} else {
result = {
localRevoked: true,
globalRevoked: false,
scope: REVOKE_SCOPE_LOCAL
};
}
state.commitRevocation(EVENT_REVOKED, result);
const result = await resolveSessionRevoke({
current,
options: opts,
onRevoke,
logger,
diagnostics
});
if (current !== null) state.commitRevocation(EVENT_REVOKED, result);
return result;
},

@ -0,0 +1,98 @@
import {
REVOKE_REASON_MISSING_REVOKE_URL,
REVOKE_REASON_NETWORK_ERROR,
REVOKE_REASON_NO_SESSION,
REVOKE_REASON_SERVER_REJECTED,
REVOKE_SCOPE_GLOBAL,
REVOKE_SCOPE_LOCAL,
SESSION_DIAGNOSTIC_EVENTS
} from './consts.ts';
import { emitSessionDiagnostic, type SessionDiagnostics } from './diagnostics.ts';
import { toError } from './session-helpers.ts';
import type { Logger } from '$libs/logr';
import type { RevokeFn, RevokeOptions, RevokeResult, Session } from './types.ts';
export interface ResolveSessionRevokeInput<TUser, TCredential = undefined, TData = undefined> {
readonly current: Session<TUser, TCredential, TData> | null;
readonly options: RevokeOptions;
readonly onRevoke?: RevokeFn<TUser, TCredential, TData>;
readonly logger?: Logger;
readonly diagnostics: SessionDiagnostics;
}
/**
* Resolve whether revoke is local, global, or degraded. The caller owns the
* actual state mutation so this helper remains pure from the engine runtime.
*/
export async function resolveSessionRevoke<TUser, TCredential = undefined, TData = undefined>({
current,
options,
onRevoke,
logger,
diagnostics
}: ResolveSessionRevokeInput<TUser, TCredential, TData>): Promise<RevokeResult> {
if (current === null) {
return {
localRevoked: true,
globalRevoked: false,
scope: REVOKE_SCOPE_LOCAL,
reason: REVOKE_REASON_NO_SESSION
};
}
const requestedScope =
options.scope ?? (onRevoke !== undefined ? REVOKE_SCOPE_GLOBAL : REVOKE_SCOPE_LOCAL);
if (requestedScope !== REVOKE_SCOPE_GLOBAL) {
return {
localRevoked: true,
globalRevoked: false,
scope: REVOKE_SCOPE_LOCAL
};
}
if (onRevoke === undefined) {
emitSessionDiagnostic(diagnostics, SESSION_DIAGNOSTIC_EVENTS.REVOKE_GLOBAL_NO_HANDLER, {
error: REVOKE_REASON_MISSING_REVOKE_URL
});
return {
localRevoked: true,
globalRevoked: false,
scope: REVOKE_SCOPE_LOCAL,
reason: REVOKE_REASON_MISSING_REVOKE_URL
};
}
try {
const ok = await onRevoke(current, { logger });
if (ok) {
return {
localRevoked: true,
globalRevoked: true,
scope: REVOKE_SCOPE_GLOBAL
};
}
emitSessionDiagnostic(
diagnostics,
SESSION_DIAGNOSTIC_EVENTS.REVOKE_GLOBAL_SERVER_REJECTED,
{ error: REVOKE_REASON_SERVER_REJECTED }
);
return {
localRevoked: true,
globalRevoked: false,
scope: REVOKE_SCOPE_LOCAL,
reason: REVOKE_REASON_SERVER_REJECTED
};
} catch (err) {
emitSessionDiagnostic(diagnostics, SESSION_DIAGNOSTIC_EVENTS.REVOKE_GLOBAL_HANDLER_FAILED, {
error: toError(err)
});
return {
localRevoked: true,
globalRevoked: false,
scope: REVOKE_SCOPE_LOCAL,
reason: REVOKE_REASON_NETWORK_ERROR
};
}
}
Loading…
Cancel
Save

Powered by TurnKey Linux.