Files
stack/v1/apps/gateway/src/harness/harness-selection.repository.ts
T

40 lines
1.5 KiB
TypeScript

import { Injectable } from '@nestjs/common';
import type { HarnessSelection } from '@mosaicstack/types';
import type { ActorTenantScope } from '../auth/session-scope.js';
/**
* TRANSITIONAL Slice-Zero selection store.
*
* This is an EXPLICITLY in-memory, owner-scoped store. It exists only so the
* Slice-Zero HTTP surfaces round-trip a selection; it is NOT durable and does not
* survive a process restart. Task Seven replaces it with the durable selection
* repository backed by the database.
*
* The store is keyed STRICTLY by the server-derived scope (userId + tenantId).
* There is no code path through which a client-supplied id chooses the key.
*/
@Injectable()
export class HarnessSelectionRepository {
private readonly byOwner = new Map<string, HarnessSelection>();
get(scope: ActorTenantScope): HarnessSelection | null {
return this.byOwner.get(ownerKey(scope)) ?? null;
}
set(scope: ActorTenantScope, selection: HarnessSelection): HarnessSelection {
// Store a normalized copy of exactly the tuple fields — nothing else is retained.
const stored: HarnessSelection = {
harnessId: selection.harnessId,
providerId: selection.providerId,
modelId: selection.modelId,
};
this.byOwner.set(ownerKey(scope), stored);
return stored;
}
}
/** Owner key from the server-derived scope only. NUL-separated to avoid collisions. */
function ownerKey(scope: ActorTenantScope): string {
return `${scope.userId}${scope.tenantId}`;
}