Move the Hub channel table, organization tags and device capability definitions into the workspace packages so the control plane and the console validate the same contract, and refresh the frozen upstream evidence for the new paths.
1515 lines
47 KiB
TypeScript
1515 lines
47 KiB
TypeScript
import { readFileSync } from 'node:fs';
|
|
import { fileURLToPath } from 'node:url';
|
|
import { upstream58e2204Operations } from './upstream-58e2204.ts';
|
|
import { DENY_REASONS, selectReadonlyOperations } from '../../test-fixtures/scripts/collector.ts';
|
|
|
|
type Risk = 'R0' | 'R1' | 'R2' | 'R3';
|
|
export type RuntimeFixtureStatus =
|
|
| 'captured-readonly'
|
|
| 'denied-readonly-candidate'
|
|
| 'not-eligible-readonly-capture'
|
|
| 'not-eligible-readonly-capture-parameterized-r0';
|
|
const routeByOwner: Record<string, string> = {
|
|
fleet: '/fleet',
|
|
'instances-new': '/instances/new',
|
|
'settings-instance': '/settings/instances/:id',
|
|
overview: '/instances/:id/overview',
|
|
cellular: '/instances/:id/cellular',
|
|
'device-network': '/instances/:id/device-network',
|
|
messages: '/instances/:id/messages',
|
|
calls: '/instances/:id/calls',
|
|
esim: '/instances/:id/esim',
|
|
notifications: '/instances/:id/notifications',
|
|
automation: '/instances/:id/automation',
|
|
ota: '/instances/:id/ota',
|
|
};
|
|
const dedicatedAuth = new Set([
|
|
'postAuthSetup',
|
|
'postAuthPassword',
|
|
'postAuthSettings',
|
|
'postAuthLogin',
|
|
'postAuthLogout',
|
|
]);
|
|
const resourceBulk = new Set([
|
|
'postSmsBatchDelete',
|
|
'postNotificationsQueueRetryAll',
|
|
'postNotificationsQueueClear',
|
|
]);
|
|
|
|
const fixtureManifest = JSON.parse(
|
|
readFileSync(
|
|
fileURLToPath(new URL('../../test-fixtures/src/manifest.json', import.meta.url)),
|
|
'utf8',
|
|
),
|
|
);
|
|
const fixtureRoot = fileURLToPath(new URL('../../test-fixtures/', import.meta.url));
|
|
const selected = selectReadonlyOperations(upstream58e2204Operations as any[]);
|
|
const selectedIds = new Set(selected.selected.map((x: any) => x.operationId));
|
|
const deniedById = new Map(selected.denied.map((x: any) => [x.operationId, x.denyReason]));
|
|
const observations = new Map<
|
|
string,
|
|
{ aliases: Set<string>; categories: Set<string>; count: number }
|
|
>();
|
|
for (const file of fixtureManifest.files) {
|
|
const envelope = JSON.parse(readFileSync(`${fixtureRoot}${file.path}`, 'utf8'));
|
|
const current = observations.get(envelope.operationId) ?? {
|
|
aliases: new Set(),
|
|
categories: new Set(),
|
|
count: 0,
|
|
};
|
|
current.aliases.add(envelope.sourceInstanceAlias);
|
|
current.categories.add(envelope.statusCategory);
|
|
current.count++;
|
|
observations.set(envelope.operationId, current);
|
|
}
|
|
export const fixtureDisposition58e2204 = upstream58e2204Operations.map((op: any) => {
|
|
const observed = observations.get(op.operationId);
|
|
if (selectedIds.has(op.operationId))
|
|
return {
|
|
operationId: op.operationId,
|
|
runtimeFixtureStatus: 'captured-readonly' as RuntimeFixtureStatus,
|
|
fixtureCount: observed?.count ?? 0,
|
|
aliases: [...(observed?.aliases ?? [])].sort(),
|
|
observedCategories: [...(observed?.categories ?? [])].sort(),
|
|
reason: 'collector-selected fully-bound GET R0; two redacted real captures',
|
|
};
|
|
const deny = deniedById.get(op.operationId);
|
|
if (deny)
|
|
return {
|
|
operationId: op.operationId,
|
|
runtimeFixtureStatus: 'denied-readonly-candidate' as RuntimeFixtureStatus,
|
|
fixtureCount: 0,
|
|
aliases: [],
|
|
observedCategories: [],
|
|
reason: deny,
|
|
};
|
|
const parameterized =
|
|
op.method === 'GET' && op.riskLevel === 'R0' && /[{}]/.test(op.pathTemplate);
|
|
return {
|
|
operationId: op.operationId,
|
|
runtimeFixtureStatus: (parameterized
|
|
? 'not-eligible-readonly-capture-parameterized-r0'
|
|
: 'not-eligible-readonly-capture') as RuntimeFixtureStatus,
|
|
fixtureCount: 0,
|
|
aliases: [],
|
|
observedCategories: [],
|
|
reason: parameterized
|
|
? 'R0 read requires bound path parameters; collector accepts only fully-bound Registry paths'
|
|
: 'not a collector-eligible fully-bound GET R0 operation',
|
|
};
|
|
});
|
|
const fixtureById = new Map(fixtureDisposition58e2204.map((x) => [x.operationId, x]));
|
|
|
|
export const acceptancePolicyCatalog = {
|
|
preconditionPolicyId: {
|
|
'query-capability':
|
|
'Registered instance, authorized actor, and runtime capability decision are required.',
|
|
'command-current-state':
|
|
'Refresh current state when available and bind the actor decision to its revision.',
|
|
'job-fresh-preflight': 'Required fresh preflight; inability to refresh blocks execution.',
|
|
'auth-dedicated':
|
|
'Dedicated auth endpoint, actor/session/instance rate limits, and fresh preflight of authentication state are required.',
|
|
},
|
|
stalePolicyId: {
|
|
'read-retain': 'Retain last success as stale and permit an explicit safe refresh.',
|
|
'write-revision':
|
|
'Refresh current state or require an explicit recorded revision-bound override.',
|
|
'high-risk-block':
|
|
'Fresh preflight is mandatory; stale, expired, or unknown state blocks execution.',
|
|
'auth-no-replay':
|
|
'Credential state is never inferred from stale data; require actor-initiated auth flow and no replay.',
|
|
},
|
|
unsupportedPolicyId: {
|
|
'version-probe':
|
|
'404/405/501 is capability evidence for this frozen version, not permanent product unsupported; retain probe evidence.',
|
|
'auth-version-probe':
|
|
'Auth 404/405/501 is version evidence; do not downgrade to a generic proxy or expose credentials.',
|
|
'ota-version-probe':
|
|
'OTA 404/405/501 is frozen-version evidence; preserve release/status probe context and never infer global support.',
|
|
},
|
|
retryPolicyId: {
|
|
'safe-read': 'Safe reads may retry within deadline and retain stale success.',
|
|
'verify-write': 'Writes require outcome verification before actor-initiated retry.',
|
|
'new-job-lineage':
|
|
'Retry creates a new Job lineage (retryOfJobId/rootJobId); never replay successful items.',
|
|
'auth-actor-only': 'No automatic replay; require an actor-initiated dedicated flow.',
|
|
},
|
|
resultPolicyId: {
|
|
'route-result': 'Structured result returns to the owning route with a redacted audit link.',
|
|
'job-result': '/jobs/:jobId contains per-item result, attempt lineage, and redacted audit.',
|
|
'auth-result':
|
|
'Dedicated auth jobs return through /jobs/:jobId; session flows return a credential metadata-only audit result and link.',
|
|
},
|
|
} as const;
|
|
|
|
/* Exact declarative UI partition. Every operation ID occurs in exactly one group; construction below throws on overlap/omission. */
|
|
const uiGroups: Record<string, string[]> = {
|
|
detail: ['getDevice', 'getSim', 'getNetwork', 'getHealth', 'getAuthStatus', 'getAuthSettings'],
|
|
table: [
|
|
'getCells',
|
|
'getNetworkInterfaces',
|
|
'getNetworkOperators',
|
|
'getDeviceNetworkWlanProfiles',
|
|
'getEsimProfiles',
|
|
'getCalls',
|
|
'getCallHistory',
|
|
'getSmsList',
|
|
'getSmsConversation',
|
|
'getNotificationsLogs',
|
|
'getNotificationsQueue',
|
|
'getAutomationLogs',
|
|
],
|
|
'dedicated-auth-flow': [
|
|
'postAuthSetup',
|
|
'postAuthPassword',
|
|
'postAuthSettings',
|
|
'postAuthLogin',
|
|
'postAuthLogout',
|
|
],
|
|
'dedicated-upload-flow': ['postOtaUpload'],
|
|
'job-action': [
|
|
'postBandLock',
|
|
'postDeviceNetworkDdnsConfig',
|
|
'postDeviceNetworkDdnsLogsClear',
|
|
'postDeviceNetworkWlanForget',
|
|
'postNetworkRegisterManual',
|
|
'postNetworkRegisterAuto',
|
|
'postCellLock',
|
|
'postCellLockUnlockAll',
|
|
'postBasebandRestart',
|
|
'postWorkMode',
|
|
'postEsimConfig',
|
|
'postEsimLpacRepair',
|
|
'deleteEsimProfilesIccid',
|
|
'postCallSettings',
|
|
'deleteCallHistoryId',
|
|
'postCallHistoryClear',
|
|
'postSmsSend',
|
|
'postSmsBatchDelete',
|
|
'deleteSmsConversationPhoneNumber',
|
|
'deleteSmsMessageId',
|
|
'postSmsClear',
|
|
'postSystemReboot',
|
|
'postServiceRestart',
|
|
'postNotificationsConfig',
|
|
'postNotificationsTestChannel',
|
|
'postNotificationsLogsClear',
|
|
'postNotificationsQueueRetryAll',
|
|
'postNotificationsQueueClear',
|
|
'deleteNotificationsQueueId',
|
|
'postNotificationsQueueIdRetry',
|
|
'postAutomationConfig',
|
|
'postAutomationLogsClear',
|
|
'postAutomationTestTaskId',
|
|
'postOtaApply',
|
|
'postOtaOnlinePrepare',
|
|
],
|
|
form: [
|
|
'postSimCache',
|
|
'postRadioMode',
|
|
'postDeviceNetworkWlanEnabled',
|
|
'postDeviceNetworkWlanConnect',
|
|
'postDeviceNetworkWlanProfile',
|
|
'postApn',
|
|
'postData',
|
|
'postRoaming',
|
|
'postAirplaneMode',
|
|
'postEsimProfiles',
|
|
'postEsimProfilesIccidRename',
|
|
'postCallDial',
|
|
'postCallHangup',
|
|
'postCallAnswer',
|
|
'postCallVolume',
|
|
'postCallForwarding',
|
|
'postOtaLatestRelease',
|
|
],
|
|
action: [
|
|
'postSimDetailsRefresh',
|
|
'postCellMonitorStart',
|
|
'postCellMonitorStop',
|
|
'postDeviceNetworkDdnsSync',
|
|
'postDeviceNetworkWlanScan',
|
|
'postDeviceNetworkWlanDisconnect',
|
|
'postEsimProfilesIccidEnable',
|
|
'postCallHangupAll',
|
|
'postOtaCancel',
|
|
],
|
|
'read-panel': [
|
|
'getRadioMode',
|
|
'getBandLock',
|
|
'getNetworkConnectionAddresses',
|
|
'getDeviceNetworkDdnsConfig',
|
|
'getDeviceNetworkDdnsStatus',
|
|
'getDeviceNetworkDdnsLogs',
|
|
'getDeviceNetworkWlanStatus',
|
|
'getNetworkSignalStrength',
|
|
'getLocationCellInfo',
|
|
'getNetworkOperatorsScan',
|
|
'getApn',
|
|
'getCellLock',
|
|
'getData',
|
|
'getRoaming',
|
|
'getAirplaneMode',
|
|
'getBasebandRestartStatus',
|
|
'getWorkMode',
|
|
'getEsimConfig',
|
|
'getEsimLpacStatus',
|
|
'getEsimEuicc',
|
|
'getCallVolume',
|
|
'getCallForwarding',
|
|
'getCallSettings',
|
|
'getImsStatus',
|
|
'getVoicemailStatus',
|
|
'getSmsStats',
|
|
'getStats',
|
|
'getStatsCpu',
|
|
'getConnectivity',
|
|
'getNotificationsConfig',
|
|
'getAutomationConfig',
|
|
'getOtaStatus',
|
|
],
|
|
};
|
|
const strategyById = new Map<string, string>();
|
|
for (const [strategy, ids] of Object.entries(uiGroups))
|
|
for (const id of ids) {
|
|
if (strategyById.has(id)) throw new Error(`duplicate acceptance override ${id}`);
|
|
strategyById.set(id, strategy);
|
|
}
|
|
const operationIds = new Set(upstream58e2204Operations.map((x: any) => x.operationId));
|
|
if (
|
|
strategyById.size !== operationIds.size ||
|
|
[...operationIds].some((id) => !strategyById.has(id))
|
|
)
|
|
throw new Error('acceptance override partition must exactly cover frozen 117 operations');
|
|
const route = (owner: string) => routeByOwner[owner];
|
|
export const surfaceGroups58e2204 = [
|
|
{ surfaceId: 'overview/device', primaryRoute: route('overview'), ids: ['getDevice'] },
|
|
{
|
|
surfaceId: 'overview/sim',
|
|
primaryRoute: route('overview'),
|
|
ids: ['getSim', 'postSimDetailsRefresh', 'postSimCache'],
|
|
},
|
|
{
|
|
surfaceId: 'overview/stats',
|
|
primaryRoute: route('overview'),
|
|
ids: ['getStats', 'getStatsCpu'],
|
|
},
|
|
{ surfaceId: 'overview/auth-health', primaryRoute: route('overview'), ids: ['getConnectivity'] },
|
|
{
|
|
surfaceId: 'overview/system-actions',
|
|
primaryRoute: route('overview'),
|
|
ids: ['postSystemReboot', 'postServiceRestart'],
|
|
},
|
|
{ surfaceId: 'cellular/serving-network', primaryRoute: route('cellular'), ids: ['getNetwork'] },
|
|
{
|
|
surfaceId: 'cellular/cells',
|
|
primaryRoute: route('cellular'),
|
|
ids: ['getCells', 'postCellMonitorStart', 'postCellMonitorStop', 'getLocationCellInfo'],
|
|
},
|
|
{
|
|
surfaceId: 'cellular/signal',
|
|
primaryRoute: route('cellular'),
|
|
ids: ['getNetworkSignalStrength'],
|
|
},
|
|
{
|
|
surfaceId: 'cellular/operator-registration',
|
|
primaryRoute: route('cellular'),
|
|
ids: [
|
|
'getNetworkOperators',
|
|
'getNetworkOperatorsScan',
|
|
'postNetworkRegisterManual',
|
|
'postNetworkRegisterAuto',
|
|
],
|
|
},
|
|
{
|
|
surfaceId: 'cellular/radio-locks',
|
|
primaryRoute: route('cellular'),
|
|
ids: [
|
|
'getRadioMode',
|
|
'postRadioMode',
|
|
'getBandLock',
|
|
'postBandLock',
|
|
'getCellLock',
|
|
'postCellLock',
|
|
'postCellLockUnlockAll',
|
|
],
|
|
},
|
|
{
|
|
surfaceId: 'cellular/data-apn',
|
|
primaryRoute: route('cellular'),
|
|
ids: [
|
|
'getApn',
|
|
'postApn',
|
|
'getData',
|
|
'postData',
|
|
'getRoaming',
|
|
'postRoaming',
|
|
'getAirplaneMode',
|
|
'postAirplaneMode',
|
|
'postBasebandRestart',
|
|
'getBasebandRestartStatus',
|
|
],
|
|
},
|
|
{
|
|
surfaceId: 'device-network/interfaces',
|
|
primaryRoute: route('device-network'),
|
|
ids: ['getNetworkInterfaces', 'getNetworkConnectionAddresses'],
|
|
},
|
|
{
|
|
surfaceId: 'device-network/ddns',
|
|
primaryRoute: route('device-network'),
|
|
ids: [
|
|
'getDeviceNetworkDdnsConfig',
|
|
'postDeviceNetworkDdnsConfig',
|
|
'getDeviceNetworkDdnsStatus',
|
|
'postDeviceNetworkDdnsSync',
|
|
'getDeviceNetworkDdnsLogs',
|
|
'postDeviceNetworkDdnsLogsClear',
|
|
],
|
|
},
|
|
{
|
|
surfaceId: 'device-network/wlan',
|
|
primaryRoute: route('device-network'),
|
|
ids: [
|
|
'getDeviceNetworkWlanStatus',
|
|
'postDeviceNetworkWlanEnabled',
|
|
'postDeviceNetworkWlanScan',
|
|
'getDeviceNetworkWlanProfiles',
|
|
'postDeviceNetworkWlanForget',
|
|
'postDeviceNetworkWlanConnect',
|
|
'postDeviceNetworkWlanDisconnect',
|
|
'postDeviceNetworkWlanProfile',
|
|
],
|
|
},
|
|
{
|
|
surfaceId: 'calls/live',
|
|
primaryRoute: route('calls'),
|
|
ids: ['getCalls', 'postCallDial', 'postCallHangup', 'postCallHangupAll', 'postCallAnswer'],
|
|
},
|
|
{
|
|
surfaceId: 'calls/volume',
|
|
primaryRoute: route('calls'),
|
|
ids: ['getCallVolume', 'postCallVolume'],
|
|
},
|
|
{
|
|
surfaceId: 'calls/forwarding',
|
|
primaryRoute: route('calls'),
|
|
ids: ['getCallForwarding', 'postCallForwarding'],
|
|
},
|
|
{
|
|
surfaceId: 'calls/settings',
|
|
primaryRoute: route('calls'),
|
|
ids: ['getCallSettings', 'postCallSettings'],
|
|
},
|
|
{
|
|
surfaceId: 'calls/history',
|
|
primaryRoute: route('calls'),
|
|
ids: ['getCallHistory', 'deleteCallHistoryId', 'postCallHistoryClear'],
|
|
},
|
|
{
|
|
surfaceId: 'calls/ims-voicemail',
|
|
primaryRoute: route('calls'),
|
|
ids: ['getImsStatus', 'getVoicemailStatus'],
|
|
},
|
|
{ surfaceId: 'messages/stats', primaryRoute: route('messages'), ids: ['getSmsStats'] },
|
|
{ surfaceId: 'messages/list', primaryRoute: route('messages'), ids: ['getSmsList'] },
|
|
{
|
|
surfaceId: 'messages/conversation',
|
|
primaryRoute: route('messages'),
|
|
ids: ['getSmsConversation'],
|
|
},
|
|
{ surfaceId: 'messages/compose', primaryRoute: route('messages'), ids: ['postSmsSend'] },
|
|
{
|
|
surfaceId: 'messages/destructive',
|
|
primaryRoute: route('messages'),
|
|
ids: [
|
|
'postSmsBatchDelete',
|
|
'deleteSmsConversationPhoneNumber',
|
|
'deleteSmsMessageId',
|
|
'postSmsClear',
|
|
],
|
|
},
|
|
{ surfaceId: 'esim/mode', primaryRoute: route('esim'), ids: ['getWorkMode', 'postWorkMode'] },
|
|
{
|
|
surfaceId: 'esim/config',
|
|
primaryRoute: route('esim'),
|
|
ids: ['getEsimConfig', 'postEsimConfig'],
|
|
},
|
|
{
|
|
surfaceId: 'esim/lpac',
|
|
primaryRoute: route('esim'),
|
|
ids: ['getEsimLpacStatus', 'postEsimLpacRepair'],
|
|
},
|
|
{ surfaceId: 'esim/euicc', primaryRoute: route('esim'), ids: ['getEsimEuicc'] },
|
|
{
|
|
surfaceId: 'esim/profiles',
|
|
primaryRoute: route('esim'),
|
|
ids: [
|
|
'getEsimProfiles',
|
|
'postEsimProfiles',
|
|
'postEsimProfilesIccidEnable',
|
|
'postEsimProfilesIccidRename',
|
|
'deleteEsimProfilesIccid',
|
|
],
|
|
},
|
|
{
|
|
surfaceId: 'notifications/config',
|
|
primaryRoute: route('notifications'),
|
|
ids: ['getNotificationsConfig', 'postNotificationsConfig', 'postNotificationsTestChannel'],
|
|
},
|
|
{
|
|
surfaceId: 'notifications/logs',
|
|
primaryRoute: route('notifications'),
|
|
ids: ['getNotificationsLogs', 'postNotificationsLogsClear'],
|
|
},
|
|
{
|
|
surfaceId: 'notifications/queue',
|
|
primaryRoute: route('notifications'),
|
|
ids: [
|
|
'getNotificationsQueue',
|
|
'postNotificationsQueueRetryAll',
|
|
'postNotificationsQueueClear',
|
|
'deleteNotificationsQueueId',
|
|
'postNotificationsQueueIdRetry',
|
|
],
|
|
},
|
|
{
|
|
surfaceId: 'automation/config',
|
|
primaryRoute: route('automation'),
|
|
ids: ['getAutomationConfig', 'postAutomationConfig'],
|
|
},
|
|
{
|
|
surfaceId: 'automation/logs',
|
|
primaryRoute: route('automation'),
|
|
ids: ['getAutomationLogs', 'postAutomationLogsClear'],
|
|
},
|
|
{
|
|
surfaceId: 'automation/task-test',
|
|
primaryRoute: route('automation'),
|
|
ids: ['postAutomationTestTaskId'],
|
|
},
|
|
{ surfaceId: 'ota/status', primaryRoute: route('ota'), ids: ['getOtaStatus', 'postOtaCancel'] },
|
|
{
|
|
surfaceId: 'ota/release',
|
|
primaryRoute: route('ota'),
|
|
ids: ['postOtaLatestRelease', 'postOtaOnlinePrepare'],
|
|
},
|
|
{ surfaceId: 'ota/upload', primaryRoute: route('ota'), ids: ['postOtaUpload'] },
|
|
{ surfaceId: 'ota/apply', primaryRoute: route('ota'), ids: ['postOtaApply'] },
|
|
{
|
|
surfaceId: 'settings/auth-settings',
|
|
primaryRoute: route('settings-instance'),
|
|
ids: ['postAuthPassword', 'getAuthSettings', 'postAuthSettings', 'postAuthLogout'],
|
|
},
|
|
{
|
|
surfaceId: 'settings/auth-entry',
|
|
primaryRoute: route('instances-new'),
|
|
ids: ['getHealth', 'getAuthStatus', 'postAuthSetup', 'postAuthLogin'],
|
|
},
|
|
] as const;
|
|
|
|
const policies = (
|
|
preconditionPolicyId: string,
|
|
stalePolicyId: string,
|
|
retryPolicyId: string,
|
|
resultPolicyId: string,
|
|
unsupportedPolicyId = 'version-probe',
|
|
) => ({ preconditionPolicyId, stalePolicyId, unsupportedPolicyId, retryPolicyId, resultPolicyId });
|
|
export const policyGroups58e2204 = [
|
|
{
|
|
groupId: 'query-list',
|
|
ids: [
|
|
'getCells',
|
|
'getNetworkInterfaces',
|
|
'getDeviceNetworkDdnsLogs',
|
|
'getDeviceNetworkWlanProfiles',
|
|
'getNetworkOperators',
|
|
'getEsimProfiles',
|
|
'getCalls',
|
|
'getCallHistory',
|
|
'getSmsList',
|
|
'getSmsConversation',
|
|
'getNotificationsLogs',
|
|
'getNotificationsQueue',
|
|
'getAutomationLogs',
|
|
],
|
|
policies: policies('query-capability', 'read-retain', 'safe-read', 'route-result'),
|
|
},
|
|
{
|
|
groupId: 'query-detail',
|
|
ids: [
|
|
'getDevice',
|
|
'getSim',
|
|
'getNetwork',
|
|
'getRadioMode',
|
|
'getBandLock',
|
|
'getNetworkConnectionAddresses',
|
|
'getDeviceNetworkDdnsConfig',
|
|
'getDeviceNetworkDdnsStatus',
|
|
'getDeviceNetworkWlanStatus',
|
|
'getNetworkSignalStrength',
|
|
'getLocationCellInfo',
|
|
'getApn',
|
|
'getCellLock',
|
|
'getData',
|
|
'getRoaming',
|
|
'getAirplaneMode',
|
|
'getBasebandRestartStatus',
|
|
'getWorkMode',
|
|
'getEsimConfig',
|
|
'getEsimLpacStatus',
|
|
'getEsimEuicc',
|
|
'getCallVolume',
|
|
'getCallForwarding',
|
|
'getCallSettings',
|
|
'getImsStatus',
|
|
'getVoicemailStatus',
|
|
'getSmsStats',
|
|
'getNotificationsConfig',
|
|
'getAutomationConfig',
|
|
'getOtaStatus',
|
|
],
|
|
policies: policies('query-capability', 'read-retain', 'safe-read', 'route-result'),
|
|
},
|
|
{
|
|
groupId: 'query-composite',
|
|
ids: ['getStats', 'getStatsCpu', 'getConnectivity'],
|
|
policies: policies('command-current-state', 'read-retain', 'safe-read', 'route-result'),
|
|
},
|
|
{
|
|
groupId: 'query-active-scan',
|
|
ids: ['getNetworkOperatorsScan'],
|
|
policies: policies('command-current-state', 'write-revision', 'verify-write', 'route-result'),
|
|
},
|
|
{
|
|
groupId: 'query-auth-detail',
|
|
ids: ['getAuthSettings', 'getHealth', 'getAuthStatus'],
|
|
policies: policies(
|
|
'query-capability',
|
|
'auth-no-replay',
|
|
'auth-actor-only',
|
|
'auth-result',
|
|
'auth-version-probe',
|
|
),
|
|
},
|
|
{
|
|
groupId: 'direct-reversible-setting',
|
|
ids: [
|
|
'postSimDetailsRefresh',
|
|
'postSimCache',
|
|
'postCellMonitorStart',
|
|
'postCellMonitorStop',
|
|
'postRadioMode',
|
|
'postDeviceNetworkDdnsSync',
|
|
'postDeviceNetworkWlanEnabled',
|
|
'postDeviceNetworkWlanScan',
|
|
'postDeviceNetworkWlanConnect',
|
|
'postDeviceNetworkWlanDisconnect',
|
|
'postDeviceNetworkWlanProfile',
|
|
'postApn',
|
|
'postData',
|
|
'postRoaming',
|
|
'postAirplaneMode',
|
|
'postEsimProfiles',
|
|
'postEsimProfilesIccidEnable',
|
|
'postEsimProfilesIccidRename',
|
|
'postCallDial',
|
|
'postCallHangup',
|
|
'postCallHangupAll',
|
|
'postCallAnswer',
|
|
'postCallVolume',
|
|
'postCallForwarding',
|
|
],
|
|
policies: policies('command-current-state', 'write-revision', 'verify-write', 'route-result'),
|
|
},
|
|
{
|
|
groupId: 'session-auth-flow',
|
|
ids: ['postAuthLogin', 'postAuthLogout'],
|
|
policies: policies(
|
|
'auth-dedicated',
|
|
'auth-no-replay',
|
|
'auth-actor-only',
|
|
'auth-result',
|
|
'auth-version-probe',
|
|
),
|
|
},
|
|
{
|
|
groupId: 'high-risk-network-job',
|
|
ids: [
|
|
'postBandLock',
|
|
'postDeviceNetworkDdnsConfig',
|
|
'postDeviceNetworkDdnsLogsClear',
|
|
'postDeviceNetworkWlanForget',
|
|
'postNetworkRegisterManual',
|
|
'postNetworkRegisterAuto',
|
|
'postCellLock',
|
|
'postCellLockUnlockAll',
|
|
'postBasebandRestart',
|
|
'postWorkMode',
|
|
'postEsimConfig',
|
|
'postEsimLpacRepair',
|
|
'postCallSettings',
|
|
'postSmsSend',
|
|
'postNotificationsConfig',
|
|
'postNotificationsTestChannel',
|
|
'postNotificationsQueueRetryAll',
|
|
'postNotificationsQueueIdRetry',
|
|
'postAutomationConfig',
|
|
'postAutomationTestTaskId',
|
|
],
|
|
policies: policies('job-fresh-preflight', 'high-risk-block', 'new-job-lineage', 'job-result'),
|
|
},
|
|
{
|
|
groupId: 'destructive-cleanup-job',
|
|
ids: [
|
|
'deleteEsimProfilesIccid',
|
|
'deleteCallHistoryId',
|
|
'postCallHistoryClear',
|
|
'postSmsBatchDelete',
|
|
'deleteSmsConversationPhoneNumber',
|
|
'deleteSmsMessageId',
|
|
'postSmsClear',
|
|
'postSystemReboot',
|
|
'postServiceRestart',
|
|
'postNotificationsLogsClear',
|
|
'postNotificationsQueueClear',
|
|
'deleteNotificationsQueueId',
|
|
'postAutomationLogsClear',
|
|
],
|
|
policies: policies('job-fresh-preflight', 'high-risk-block', 'new-job-lineage', 'job-result'),
|
|
},
|
|
{
|
|
groupId: 'ota-direct-control',
|
|
ids: ['postOtaLatestRelease', 'postOtaCancel'],
|
|
policies: policies('command-current-state', 'write-revision', 'verify-write', 'route-result'),
|
|
},
|
|
{
|
|
groupId: 'ota-job',
|
|
ids: ['postOtaUpload', 'postOtaOnlinePrepare', 'postOtaApply'],
|
|
policies: policies(
|
|
'job-fresh-preflight',
|
|
'high-risk-block',
|
|
'new-job-lineage',
|
|
'job-result',
|
|
'ota-version-probe',
|
|
),
|
|
},
|
|
{
|
|
groupId: 'high-risk-auth-flow',
|
|
ids: ['postAuthPassword', 'postAuthSettings', 'postAuthSetup'],
|
|
policies: policies(
|
|
'auth-dedicated',
|
|
'auth-no-replay',
|
|
'new-job-lineage',
|
|
'auth-result',
|
|
'auth-version-probe',
|
|
),
|
|
},
|
|
] as const;
|
|
|
|
const readScenario = (empty: boolean, partial: boolean) => ({
|
|
empty: {
|
|
applicable: empty,
|
|
rationale: empty
|
|
? 'Successful collection may contain no rows.'
|
|
: 'Detail resource has no collection-empty rendering.',
|
|
},
|
|
partial: {
|
|
applicable: partial,
|
|
rationale: partial
|
|
? 'Independent response sections may succeed or fail.'
|
|
: 'Atomic detail read has no meaningful partial rendering.',
|
|
},
|
|
'policy-forbidden': {
|
|
applicable: false,
|
|
rationale: 'Safe read has no write-confirmation policy; support remains orthogonal.',
|
|
},
|
|
'unknown-result': {
|
|
applicable: false,
|
|
rationale: 'Read failure is an error/freshness state, not unknown write outcome.',
|
|
},
|
|
'owner-switch': {
|
|
applicable: true,
|
|
rationale: 'Owner switch discards responses with a mismatched instance key.',
|
|
},
|
|
});
|
|
const writeScenario = (partial: boolean) => ({
|
|
empty: { applicable: false, rationale: 'Command result is not a collection-empty state.' },
|
|
partial: {
|
|
applicable: partial,
|
|
rationale: partial
|
|
? 'Job items may independently succeed, fail, or be skipped.'
|
|
: 'Single-target command has no meaningful partial result.',
|
|
},
|
|
'policy-forbidden': {
|
|
applicable: true,
|
|
rationale: 'Write can be blocked by capability, authorization, risk, or preflight policy.',
|
|
},
|
|
'unknown-result': {
|
|
applicable: true,
|
|
rationale: 'Disconnect or timeout requires outcome verification before retry.',
|
|
},
|
|
'owner-switch': {
|
|
applicable: true,
|
|
rationale: 'Owner switch preserves execution lineage but discards mismatched route responses.',
|
|
},
|
|
});
|
|
const activeScanScenario = {
|
|
empty: {
|
|
applicable: true,
|
|
rationale: 'A successful active operator scan may return no operators.',
|
|
},
|
|
partial: {
|
|
applicable: true,
|
|
rationale:
|
|
'The scan response may contain usable operators alongside per-result failures or incomplete entries.',
|
|
},
|
|
'policy-forbidden': {
|
|
applicable: true,
|
|
rationale:
|
|
'Active scan may be blocked by capability, authorization, preflight, or active-scan policy.',
|
|
},
|
|
'unknown-result': {
|
|
applicable: false,
|
|
rationale:
|
|
'A timed-out scan result may be discarded; it is not an unknown persistent write outcome.',
|
|
},
|
|
'owner-switch': {
|
|
applicable: true,
|
|
rationale: 'Owner switch discards scan responses with a mismatched instance key.',
|
|
},
|
|
};
|
|
export const scenarioGroups58e2204 = [
|
|
{
|
|
profileId: 'list-read',
|
|
ids: [
|
|
'getCells',
|
|
'getNetworkInterfaces',
|
|
'getDeviceNetworkDdnsLogs',
|
|
'getDeviceNetworkWlanProfiles',
|
|
'getNetworkOperators',
|
|
'getEsimProfiles',
|
|
'getCalls',
|
|
'getCallHistory',
|
|
'getSmsList',
|
|
'getSmsConversation',
|
|
'getNotificationsLogs',
|
|
'getNotificationsQueue',
|
|
'getAutomationLogs',
|
|
],
|
|
scenarios: readScenario(true, true),
|
|
},
|
|
{
|
|
profileId: 'detail-read',
|
|
ids: [
|
|
'getDevice',
|
|
'getSim',
|
|
'getNetwork',
|
|
'getRadioMode',
|
|
'getBandLock',
|
|
'getNetworkConnectionAddresses',
|
|
'getDeviceNetworkDdnsConfig',
|
|
'getDeviceNetworkDdnsStatus',
|
|
'getDeviceNetworkWlanStatus',
|
|
'getNetworkSignalStrength',
|
|
'getLocationCellInfo',
|
|
'getApn',
|
|
'getCellLock',
|
|
'getData',
|
|
'getRoaming',
|
|
'getAirplaneMode',
|
|
'getBasebandRestartStatus',
|
|
'getWorkMode',
|
|
'getEsimConfig',
|
|
'getEsimLpacStatus',
|
|
'getEsimEuicc',
|
|
'getCallVolume',
|
|
'getCallForwarding',
|
|
'getCallSettings',
|
|
'getImsStatus',
|
|
'getVoicemailStatus',
|
|
'getSmsStats',
|
|
'getNotificationsConfig',
|
|
'getAutomationConfig',
|
|
'getOtaStatus',
|
|
'getAuthSettings',
|
|
'getHealth',
|
|
'getAuthStatus',
|
|
],
|
|
scenarios: readScenario(false, false),
|
|
},
|
|
{
|
|
profileId: 'composite-read',
|
|
ids: ['getStats', 'getStatsCpu', 'getConnectivity'],
|
|
scenarios: readScenario(false, true),
|
|
},
|
|
{ profileId: 'active-scan', ids: ['getNetworkOperatorsScan'], scenarios: activeScanScenario },
|
|
{
|
|
profileId: 'direct-write',
|
|
ids: [
|
|
'postSimDetailsRefresh',
|
|
'postSimCache',
|
|
'postCellMonitorStart',
|
|
'postCellMonitorStop',
|
|
'postRadioMode',
|
|
'postDeviceNetworkDdnsSync',
|
|
'postDeviceNetworkWlanEnabled',
|
|
'postDeviceNetworkWlanScan',
|
|
'postDeviceNetworkWlanConnect',
|
|
'postDeviceNetworkWlanDisconnect',
|
|
'postDeviceNetworkWlanProfile',
|
|
'postApn',
|
|
'postData',
|
|
'postRoaming',
|
|
'postAirplaneMode',
|
|
'postEsimProfiles',
|
|
'postEsimProfilesIccidEnable',
|
|
'postEsimProfilesIccidRename',
|
|
'postCallDial',
|
|
'postCallHangup',
|
|
'postCallHangupAll',
|
|
'postCallAnswer',
|
|
'postCallVolume',
|
|
'postCallForwarding',
|
|
],
|
|
scenarios: writeScenario(false),
|
|
},
|
|
{
|
|
profileId: 'job-single',
|
|
ids: [
|
|
'postBandLock',
|
|
'postDeviceNetworkDdnsConfig',
|
|
'postDeviceNetworkDdnsLogsClear',
|
|
'postDeviceNetworkWlanForget',
|
|
'postNetworkRegisterManual',
|
|
'postNetworkRegisterAuto',
|
|
'postCellLock',
|
|
'postCellLockUnlockAll',
|
|
'postWorkMode',
|
|
'postEsimConfig',
|
|
'postEsimLpacRepair',
|
|
'postCallSettings',
|
|
'postSmsSend',
|
|
'postNotificationsConfig',
|
|
'postNotificationsTestChannel',
|
|
'postNotificationsQueueIdRetry',
|
|
'postAutomationConfig',
|
|
'postAutomationTestTaskId',
|
|
'deleteEsimProfilesIccid',
|
|
'deleteCallHistoryId',
|
|
'postCallHistoryClear',
|
|
'deleteSmsConversationPhoneNumber',
|
|
'deleteSmsMessageId',
|
|
'postSmsClear',
|
|
'postBasebandRestart',
|
|
'postSystemReboot',
|
|
'postServiceRestart',
|
|
'postNotificationsLogsClear',
|
|
'deleteNotificationsQueueId',
|
|
'postAutomationLogsClear',
|
|
],
|
|
scenarios: writeScenario(false),
|
|
},
|
|
{
|
|
profileId: 'job-resource-bulk',
|
|
ids: ['postSmsBatchDelete', 'postNotificationsQueueRetryAll', 'postNotificationsQueueClear'],
|
|
scenarios: writeScenario(true),
|
|
},
|
|
{
|
|
profileId: 'ota-direct',
|
|
ids: ['postOtaLatestRelease', 'postOtaCancel'],
|
|
scenarios: writeScenario(false),
|
|
},
|
|
{
|
|
profileId: 'ota-job-single',
|
|
ids: ['postOtaUpload', 'postOtaOnlinePrepare', 'postOtaApply'],
|
|
scenarios: writeScenario(false),
|
|
},
|
|
{
|
|
profileId: 'auth-flow',
|
|
ids: [
|
|
'postAuthPassword',
|
|
'postAuthSettings',
|
|
'postAuthSetup',
|
|
'postAuthLogin',
|
|
'postAuthLogout',
|
|
],
|
|
scenarios: writeScenario(false),
|
|
},
|
|
] as const;
|
|
|
|
const versionEvidencePolicy =
|
|
'Persist the audited commit plus runtime capability probes; 404/405/501 is version-scoped evidence and never a permanent global verdict.';
|
|
export const availabilityGroups58e2204 = [
|
|
{
|
|
groupId: 'captured-real-read',
|
|
realAcceptance: 'REAL_READ',
|
|
availability: 'planned',
|
|
reason:
|
|
'Frozen-scope read has two redacted captured responses; runtime support is still decided per registered instance.',
|
|
versionEvidencePolicy,
|
|
ids: [
|
|
'getDevice',
|
|
'getSim',
|
|
'getNetwork',
|
|
'getCells',
|
|
'getRadioMode',
|
|
'getBandLock',
|
|
'getNetworkInterfaces',
|
|
'getNetworkConnectionAddresses',
|
|
'getDeviceNetworkDdnsConfig',
|
|
'getDeviceNetworkDdnsStatus',
|
|
'getDeviceNetworkWlanStatus',
|
|
'getDeviceNetworkWlanProfiles',
|
|
'getNetworkSignalStrength',
|
|
'getLocationCellInfo',
|
|
'getNetworkOperators',
|
|
'getApn',
|
|
'getCellLock',
|
|
'getData',
|
|
'getRoaming',
|
|
'getAirplaneMode',
|
|
'getBasebandRestartStatus',
|
|
'getWorkMode',
|
|
'getEsimConfig',
|
|
'getEsimLpacStatus',
|
|
'getCalls',
|
|
'getCallVolume',
|
|
'getCallForwarding',
|
|
'getCallSettings',
|
|
'getImsStatus',
|
|
'getVoicemailStatus',
|
|
'getSmsStats',
|
|
'getStats',
|
|
'getStatsCpu',
|
|
'getNotificationsConfig',
|
|
'getAutomationConfig',
|
|
'getOtaStatus',
|
|
'getAuthSettings',
|
|
'getHealth',
|
|
'getAuthStatus',
|
|
],
|
|
},
|
|
{
|
|
groupId: 'denied-read-candidate',
|
|
realAcceptance: 'REAL_READ_DEFERRED',
|
|
availability: 'planned',
|
|
reason:
|
|
'Frozen-scope read is modeled but real capture was explicitly denied; runtime support is probed per instance.',
|
|
versionEvidencePolicy,
|
|
ids: [
|
|
'getDeviceNetworkDdnsLogs',
|
|
'getNetworkOperatorsScan',
|
|
'getEsimEuicc',
|
|
'getEsimProfiles',
|
|
'getCallHistory',
|
|
'getSmsList',
|
|
'getSmsConversation',
|
|
'getConnectivity',
|
|
'getNotificationsLogs',
|
|
'getNotificationsQueue',
|
|
'getAutomationLogs',
|
|
],
|
|
},
|
|
{
|
|
groupId: 'write-later',
|
|
realAcceptance: 'REAL_WRITE_LATER',
|
|
availability: 'planned',
|
|
reason:
|
|
'Frozen-scope reversible command is contract-planned for a later controlled real-write acceptance phase.',
|
|
versionEvidencePolicy,
|
|
ids: [
|
|
'postSimDetailsRefresh',
|
|
'postSimCache',
|
|
'postCellMonitorStart',
|
|
'postCellMonitorStop',
|
|
'postRadioMode',
|
|
'postDeviceNetworkDdnsSync',
|
|
'postDeviceNetworkWlanEnabled',
|
|
'postDeviceNetworkWlanScan',
|
|
'postDeviceNetworkWlanConnect',
|
|
'postDeviceNetworkWlanDisconnect',
|
|
'postDeviceNetworkWlanProfile',
|
|
'postApn',
|
|
'postData',
|
|
'postRoaming',
|
|
'postAirplaneMode',
|
|
'postEsimProfiles',
|
|
'postEsimProfilesIccidEnable',
|
|
'postEsimProfilesIccidRename',
|
|
'postCallDial',
|
|
'postCallHangup',
|
|
'postCallHangupAll',
|
|
'postCallAnswer',
|
|
'postCallVolume',
|
|
'postCallForwarding',
|
|
'postOtaLatestRelease',
|
|
'postOtaCancel',
|
|
'postAuthLogin',
|
|
'postAuthLogout',
|
|
],
|
|
},
|
|
{
|
|
groupId: 'high-risk-simulated',
|
|
realAcceptance: 'SIMULATED_HIGH_RISK',
|
|
availability: 'planned',
|
|
reason:
|
|
'Frozen-scope high-risk operation is planned with simulation-only acceptance until controlled safety authorization exists.',
|
|
versionEvidencePolicy,
|
|
ids: [
|
|
'postBandLock',
|
|
'postDeviceNetworkDdnsConfig',
|
|
'postDeviceNetworkDdnsLogsClear',
|
|
'postDeviceNetworkWlanForget',
|
|
'postNetworkRegisterManual',
|
|
'postNetworkRegisterAuto',
|
|
'postCellLock',
|
|
'postCellLockUnlockAll',
|
|
'postBasebandRestart',
|
|
'postWorkMode',
|
|
'postEsimConfig',
|
|
'postEsimLpacRepair',
|
|
'deleteEsimProfilesIccid',
|
|
'postCallSettings',
|
|
'deleteCallHistoryId',
|
|
'postCallHistoryClear',
|
|
'postSmsSend',
|
|
'postSmsBatchDelete',
|
|
'deleteSmsConversationPhoneNumber',
|
|
'deleteSmsMessageId',
|
|
'postSmsClear',
|
|
'postSystemReboot',
|
|
'postServiceRestart',
|
|
'postNotificationsConfig',
|
|
'postNotificationsTestChannel',
|
|
'postNotificationsLogsClear',
|
|
'postNotificationsQueueRetryAll',
|
|
'postNotificationsQueueClear',
|
|
'deleteNotificationsQueueId',
|
|
'postNotificationsQueueIdRetry',
|
|
'postAutomationConfig',
|
|
'postAutomationLogsClear',
|
|
'postAutomationTestTaskId',
|
|
'postOtaUpload',
|
|
'postOtaOnlinePrepare',
|
|
'postOtaApply',
|
|
'postAuthPassword',
|
|
'postAuthSettings',
|
|
'postAuthSetup',
|
|
],
|
|
},
|
|
] as const;
|
|
|
|
function exactLookup(groups: readonly any[], label: string) {
|
|
const map = new Map<string, any>();
|
|
for (const group of groups)
|
|
for (const id of group.ids) {
|
|
if (map.has(id)) throw new Error(`${label} overlap: ${id}`);
|
|
map.set(id, group);
|
|
}
|
|
for (const id of map.keys())
|
|
if (!operationIds.has(id)) throw new Error(`${label} unknown operation: ${id}`);
|
|
if (map.size !== operationIds.size || [...operationIds].some((id) => !map.has(id)))
|
|
throw new Error(`${label} must exactly cover frozen 117 operations`);
|
|
return map;
|
|
}
|
|
const surfaceById = exactLookup(surfaceGroups58e2204, 'surface');
|
|
const policyById = exactLookup(policyGroups58e2204, 'policy');
|
|
const scenarioById = exactLookup(scenarioGroups58e2204, 'scenario');
|
|
const availabilityById = exactLookup(availabilityGroups58e2204, 'availability');
|
|
export const operationAcceptanceOverrides58e2204 = Object.fromEntries(
|
|
upstream58e2204Operations.map((op: any) => {
|
|
const surface = surfaceById.get(op.operationId);
|
|
const policy = policyById.get(op.operationId);
|
|
const scenario = scenarioById.get(op.operationId);
|
|
const availability = availabilityById.get(op.operationId);
|
|
if (!surface || !policy || !scenario || !availability)
|
|
throw new Error(`missing exact acceptance decision: ${op.operationId}`);
|
|
return [
|
|
op.operationId,
|
|
{
|
|
surfaceId: surface.surfaceId,
|
|
primaryRoute: surface.primaryRoute,
|
|
uiStrategy: strategyById.get(op.operationId),
|
|
...policy.policies,
|
|
scenarioAcceptance: scenario.scenarios,
|
|
availability: availability.availability,
|
|
availabilityReason: availability.reason,
|
|
versionEvidencePolicy: availability.versionEvidencePolicy,
|
|
realAcceptance: availability.realAcceptance,
|
|
},
|
|
];
|
|
}),
|
|
);
|
|
export const operationAcceptance58e2204 = upstream58e2204Operations.map((op: any) => {
|
|
const override: any = operationAcceptanceOverrides58e2204[op.operationId];
|
|
const policies: any = acceptancePolicyCatalog;
|
|
const high = ['R2', 'R3'].includes(op.riskLevel);
|
|
const auth = dedicatedAuth.has(op.operationId);
|
|
const scenarios = override.scenarioAcceptance;
|
|
return {
|
|
operationId: op.operationId,
|
|
method: op.method,
|
|
pathTemplate: op.pathTemplate,
|
|
upstreamDomain: op.upstreamDomain,
|
|
primaryRoute: override.primaryRoute,
|
|
surfaceId: override.surfaceId,
|
|
uiStrategy: override.uiStrategy,
|
|
availability: override.availability,
|
|
availabilityReason: override.availabilityReason,
|
|
versionEvidencePolicy: override.versionEvidencePolicy,
|
|
requiredStates: {
|
|
request: ['idle', 'loading', 'success', 'error'],
|
|
freshness: ['fresh', 'stale', 'expired', 'unknown'],
|
|
support: ['supported', 'unsupported', 'auth-required', 'degraded', 'unknown'],
|
|
scenarios: Object.entries(scenarios)
|
|
.filter(([, v]: any) => v.applicable)
|
|
.map(([k]) => k),
|
|
naRationale: 'Non-applicable scenarios retain an explicit rationale in scenarioAcceptance.',
|
|
},
|
|
scenarioAcceptance: scenarios,
|
|
riskLevel: op.riskLevel as Risk,
|
|
confirmationUX: op.confirmationPolicy,
|
|
executionMode: auth ? 'dedicated-flow' : high ? 'preparation-job' : 'direct',
|
|
executionDerivation: auth
|
|
? 'Registry executionPolicy=dedicatedFlow binds the dedicated authentication orchestration.'
|
|
: high
|
|
? 'Registry capability=job plus product prepare-confirm-execute policy derives preparation-job orchestration.'
|
|
: 'Registry capability plus acceptance policy derives direct structured execution.',
|
|
executionPolicySource:
|
|
'Registry supplies risk, confirmation, capability and dedicatedFlow; acceptance policy supplies orchestration.',
|
|
...Object.fromEntries(
|
|
[
|
|
'preconditionPolicyId',
|
|
'stalePolicyId',
|
|
'unsupportedPolicyId',
|
|
'retryPolicyId',
|
|
'resultPolicyId',
|
|
].map((k) => [k, override[k]]),
|
|
),
|
|
preconditions: policies.preconditionPolicyId[override.preconditionPolicyId],
|
|
stalePolicy: policies.stalePolicyId[override.stalePolicyId],
|
|
unsupportedPolicy: policies.unsupportedPolicyId[override.unsupportedPolicyId],
|
|
retryRecovery: policies.retryPolicyId[override.retryPolicyId],
|
|
resultDestination: policies.resultPolicyId[override.resultPolicyId],
|
|
resourceBulk: resourceBulk.has(op.operationId),
|
|
fleetBatchable: op.operationId === 'getHealth',
|
|
partialAggregationPolicy:
|
|
op.operationId === 'getHealth'
|
|
? 'per-item'
|
|
: resourceBulk.has(op.operationId)
|
|
? 'resource-item'
|
|
: 'not-applicable',
|
|
realAcceptance: override.realAcceptance,
|
|
evidenceIds: [
|
|
`registry:${op.operationId}`,
|
|
...op.sourceEvidence.map((x: string) => `upstream:${x}`),
|
|
`fixture:${fixtureById.get(op.operationId)?.runtimeFixtureStatus}`,
|
|
],
|
|
...(op.sessionSensitive ? { sessionSubtype: 'session-sensitive' } : {}),
|
|
};
|
|
});
|
|
|
|
const flow = (
|
|
flowId: string,
|
|
route: string,
|
|
risk: string,
|
|
riskSubtype: string,
|
|
confirmation: string,
|
|
preconditions: string,
|
|
result: string,
|
|
failureRecovery: string,
|
|
secretPolicy: string,
|
|
evidence: string,
|
|
) => ({
|
|
flowId,
|
|
route,
|
|
risk,
|
|
riskSubtype,
|
|
confirmation,
|
|
preconditions,
|
|
result,
|
|
failureRecovery,
|
|
secretPolicy,
|
|
evidence,
|
|
});
|
|
export const controlPlaneAcceptance = [
|
|
flow(
|
|
'instance-create',
|
|
'/instances/new',
|
|
'R1',
|
|
'configuration',
|
|
'diff-confirm',
|
|
'canonical origin and unique stable ID',
|
|
'created instance revision and audit',
|
|
'retain draft on validation or reconcile failure',
|
|
'secret reference only; never return a value',
|
|
'WF-01 + product policy',
|
|
),
|
|
flow(
|
|
'instance-update',
|
|
'/settings/instances/:id',
|
|
'R1',
|
|
'configuration',
|
|
'revision-diff',
|
|
'current revision',
|
|
'updated revision and audit',
|
|
'409 refreshes diff without losing edits',
|
|
'preserve/set/clear explicit; never return a value',
|
|
'WF-01 + product policy',
|
|
),
|
|
flow(
|
|
'instance-delete',
|
|
'/settings/instances/:id',
|
|
'R3',
|
|
'destructive',
|
|
'strong target restatement',
|
|
'fresh revision and no conflicting job',
|
|
'new jobId with two-phase deleting to tombstone result',
|
|
'before boundary restore; after boundary manual recovery',
|
|
'destroy reference without reading secret value',
|
|
'WF-13',
|
|
),
|
|
flow(
|
|
'secret-set',
|
|
'/settings/instances/:id',
|
|
'R1',
|
|
'secret-reference',
|
|
'explicit set',
|
|
'authorized SecretStore write',
|
|
'new reference metadata and audit',
|
|
'atomic rollback on reference write failure',
|
|
'never return or log secret value',
|
|
'WF-01',
|
|
),
|
|
flow(
|
|
'secret-preserve',
|
|
'/settings/instances/:id',
|
|
'R1',
|
|
'secret-reference',
|
|
'explicit preserve',
|
|
'existing reference metadata',
|
|
'unchanged reference metadata and audit',
|
|
'revision conflict refreshes metadata only',
|
|
'never read or return secret value',
|
|
'WF-01',
|
|
),
|
|
flow(
|
|
'secret-clear',
|
|
'/settings/instances/:id',
|
|
'R1',
|
|
'secret-reference',
|
|
'explicit clear',
|
|
'fresh revision',
|
|
'reference removed and audit',
|
|
'atomic rollback or explicit recovery state',
|
|
'never return destroyed secret value',
|
|
'WF-01',
|
|
),
|
|
flow(
|
|
'config-import-preview',
|
|
'/settings/instances',
|
|
'R0',
|
|
'preview',
|
|
'none',
|
|
'validated upload and canonical origins',
|
|
'redacted diff/conflict/count preview',
|
|
'fix file and regenerate preview',
|
|
'never include secret values in preview',
|
|
'IA settings import',
|
|
),
|
|
flow(
|
|
'config-import-confirm',
|
|
'/settings/instances',
|
|
'R2',
|
|
'bulk-configuration',
|
|
'explicit preview token',
|
|
'fresh unexpired preview',
|
|
'new jobId with per-instance items',
|
|
'retry failed items in new lineage',
|
|
'references only; never import/export secret values',
|
|
'IA settings import',
|
|
),
|
|
flow(
|
|
'credential-verify',
|
|
'/instances/new',
|
|
'R1',
|
|
'session-sensitive',
|
|
'actor initiated',
|
|
'rate limit and registered target',
|
|
'credential metadata-only result',
|
|
'no automatic replay; actor may retry after backoff',
|
|
'ephemeral input, never response/audit value',
|
|
'WF-01',
|
|
),
|
|
flow(
|
|
'saved-secret-login',
|
|
'/instances/new',
|
|
'R1',
|
|
'session-sensitive',
|
|
'actor initiated',
|
|
'saved reference and rate limit',
|
|
'session metadata-only result',
|
|
'no automatic replay; return to login flow',
|
|
'resolve server-side; never expose value',
|
|
'WF-12',
|
|
),
|
|
flow(
|
|
'temporary-secret-login',
|
|
'/instances/new',
|
|
'R1',
|
|
'session-sensitive',
|
|
'actor initiated',
|
|
'one-shot input and rate limit',
|
|
'session metadata-only result',
|
|
'no automatic replay; require new actor input',
|
|
'memory-only and never saved or returned',
|
|
'WF-12',
|
|
),
|
|
flow(
|
|
'logout',
|
|
'/settings/instances/:id',
|
|
'R1',
|
|
'session-sensitive',
|
|
'actor initiated',
|
|
'active session',
|
|
'session cleared and metadata audit',
|
|
'no replay; reconcile auth status',
|
|
'no credential value involved',
|
|
'WF-12',
|
|
),
|
|
flow(
|
|
'401-recovery',
|
|
'/instances/:id/overview',
|
|
'R1',
|
|
'session-recovery',
|
|
'actor chooses login',
|
|
'401 evidence and retained stale data',
|
|
'return to owner; retry R0 only',
|
|
'never replay writes; preserve draft for new prepare',
|
|
'temporary/saved secret follows selected login policy',
|
|
'WF-12',
|
|
),
|
|
flow(
|
|
'auth-setup',
|
|
'/instances/new',
|
|
'R3',
|
|
'authentication-change',
|
|
'strong confirmation',
|
|
'fresh dedicated auth preflight',
|
|
'new jobId and metadata-only audit',
|
|
'new lineage after state verification',
|
|
'password never returned or audited',
|
|
'Registry postAuthSetup',
|
|
),
|
|
flow(
|
|
'auth-password-change',
|
|
'/settings/instances/:id',
|
|
'R3',
|
|
'authentication-change',
|
|
'strong confirmation',
|
|
'fresh dedicated auth preflight',
|
|
'new jobId and metadata-only audit',
|
|
'new lineage after auth-status verification',
|
|
'old/new password never returned or audited',
|
|
'Registry postAuthPassword',
|
|
),
|
|
flow(
|
|
'auth-settings-read',
|
|
'/settings/instances/:id',
|
|
'R0',
|
|
'authentication-read',
|
|
'none',
|
|
'registered instance and actor',
|
|
'structured auth settings',
|
|
'safe actor retry',
|
|
'no password/cookie/token fields',
|
|
'Registry getAuthSettings',
|
|
),
|
|
flow(
|
|
'auth-settings-write',
|
|
'/settings/instances/:id',
|
|
'R2',
|
|
'authentication-change',
|
|
'explicit confirmation',
|
|
'fresh dedicated auth preflight',
|
|
'new jobId and metadata-only audit',
|
|
'new lineage; no replay',
|
|
'never return credential values',
|
|
'Registry postAuthSettings',
|
|
),
|
|
flow(
|
|
'job-cancel',
|
|
'/jobs/:jobId',
|
|
'R1',
|
|
'job-control',
|
|
'explicit confirmation',
|
|
'cancelable current phase',
|
|
'immutable cancellation event',
|
|
'show non-cancelable boundary and reconcile',
|
|
'no secret data in event',
|
|
'IA jobs',
|
|
),
|
|
flow(
|
|
'job-retry',
|
|
'/jobs/:jobId',
|
|
'R2',
|
|
'job-control',
|
|
'explicit failed-item selection',
|
|
'source terminal state and fresh preflight',
|
|
'new jobId with retryOf/root/source lineage',
|
|
'never mutate source or replay successful items',
|
|
'redacted parameter summary only',
|
|
'WF-10',
|
|
),
|
|
flow(
|
|
'audit-export',
|
|
'/audit',
|
|
'R0',
|
|
'data-export',
|
|
'explicit scope',
|
|
'authorized filters',
|
|
'redacted export artifact',
|
|
'regenerate from immutable audit',
|
|
'redaction applies; no sensitiveFields',
|
|
'WF-11',
|
|
),
|
|
flow(
|
|
'system-settings-update',
|
|
'/settings/system',
|
|
'R1',
|
|
'configuration',
|
|
'revision-diff',
|
|
'safe bounds and current revision',
|
|
'updated revision and audit',
|
|
'409 refreshes diff; invalid bounds rejected',
|
|
'no secrets accepted',
|
|
'IA settings system',
|
|
),
|
|
];
|
|
|
|
const esc = (v: any) => String(v).replace(/\|/g, '\\|').replace(/\n/g, ' ');
|
|
export function renderOperationAcceptanceMatrix() {
|
|
const controlRows = controlPlaneAcceptance
|
|
.map(
|
|
(x) =>
|
|
`| \`${x.flowId}\` | \`${x.route}\` | ${x.risk} / ${x.riskSubtype} | ${x.confirmation} | ${esc(x.preconditions)} | ${esc(x.result)} | ${esc(x.failureRecovery)} | ${esc(x.secretPolicy)} | ${esc(x.evidence)} |`,
|
|
)
|
|
.join('\n');
|
|
const rows = operationAcceptance58e2204
|
|
.map((x: any) => {
|
|
const f: any = fixtureById.get(x.operationId);
|
|
const scenarios = Object.entries(x.scenarioAcceptance)
|
|
.map(([k, v]: any) => `${k}:${v.applicable ? 'Y' : 'N'} (${v.rationale})`)
|
|
.join('<br>');
|
|
const policies = `${x.preconditionPolicyId}/${x.stalePolicyId}/${x.unsupportedPolicyId}/${x.retryPolicyId}/${x.resultPolicyId}`;
|
|
const categories = f.observedCategories.length
|
|
? [...f.observedCategories].sort().join(',')
|
|
: 'none';
|
|
return `| \`${x.operationId}\` | ${x.method} \`${x.pathTemplate}\` | ${x.upstreamDomain} | \`${x.primaryRoute}\`<br>\`${x.surfaceId}\` | ${x.uiStrategy} | ${x.availability}: ${esc(x.availabilityReason)}<br>${esc(x.versionEvidencePolicy)} | ${scenarios} | ${x.riskLevel}; ${x.confirmationUX}<br>${x.executionMode} | ${policies}<br>${esc(x.preconditions)}<br>${esc(x.stalePolicy)}<br>${esc(x.unsupportedPolicy)}<br>${esc(x.retryRecovery)}<br>${esc(x.resultDestination)} | ${x.realAcceptance} | ${f.runtimeFixtureStatus}; n=${f.fixtureCount}; categories=${categories}; ${esc(f.reason)} | ${x.evidenceIds.map((e: string) => `\`${e}\``).join('<br>')} |`;
|
|
})
|
|
.join('\n');
|
|
return `# Operation acceptance matrix — upstream 58e2204\n\n> Generated from the structured ledger. Registry is the sole source for risk, confirmation, capability, and dedicated-flow facts; orchestration is bound by acceptance policy. \`registeredOperation\` is not a synonym for preparation Job.\n\nREAL_READ means captured evidence and is restricted to \`captured-readonly\`. REAL_READ_DEFERRED marks denied candidates without a real fixture. Fixture disposition is metadata-only: runtime status, count, safe observed status categories, and reason; it never renders fixture body/response, alias, identity, or URL.\n\n## Control-plane acceptance (independent flows)\n\n| flowId | route | risk / subtype | confirmation | preconditions | result | failure recovery | secret policy | evidence |\n|---|---|---|---|---|---|---|---|---|\n${controlRows}\n\n## Upstream operation acceptance (exact 117)\n\n| operationId | method/path | domain | route/surface | UI | availability/version evidence | scenario applicability | risk/confirmation/execution | policy IDs and resolved policies | real class | fixture disposition (metadata-only: runtime status / n / categories / reason) | evidence |\n|---|---|---|---|---|---|---|---|---|---|---|---|\n${rows}\n`;
|
|
}
|
|
export const fixtureDenyReasons58e2204 = DENY_REASONS;
|