Publish curated Unraid-AppOps-Gateway source from ad0a390e431166c3198a2ac3bec010c2b44f2dea

This commit is contained in:
Public Source Publisher committed 2026-10-02 09:56:13 +00:00
1 parent 29c1e3d5a1
commit 98d31477f9
35 files changed
+7264 -185

No files matched your search

+216
View File
@@ -0,0 +1,216 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import {
buildEnrollmentStorageView,
buildStorageRootSelection,
canInitializeManagedStorage,
canRequestManagedStorageInitialization,
canSaveStorageRootSelection,
LEGACY_APPDATA_ROOT,
MANAGED_APPDATA_ROOT,
MANAGED_STORAGE_INITIALIZE_ACTION,
MANAGED_STORAGE_TARGET,
normalizeManagedStoragePreview,
normalizeManagedStorageActionOutcome,
} from './enrollmentStorageView.ts';
const baseTrust = {
configured: true,
status: 'ready',
trustedAppdataRoot: MANAGED_APPDATA_ROOT,
managedAppdataBackupAcknowledged: true,
};
const baseCapabilities = {
availableTrustedAppdataRoots: [
{ root: LEGACY_APPDATA_ROOT, status: 'ready' },
{ root: MANAGED_APPDATA_ROOT, status: 'needs_initialization' },
],
managedStorage: {
status: 'initialization_required',
blockerCode: 'managed_appdata_initialization_required',
root: MANAGED_APPDATA_ROOT,
backupScope: 'dockerRootDir',
backupAcknowledged: true,
},
};
test('malformed or unknown roots fail closed without echoing untrusted paths', () => {
const view = buildEnrollmentStorageView({ ...baseTrust, trustedAppdataRoot: '/tmp/unknown-secret-path' }, {
...baseCapabilities,
availableTrustedAppdataRoots: [{ root: '/tmp/private', status: 'ready' }, ...baseCapabilities.availableTrustedAppdataRoots],
});
assert.equal(view.currentRoot, null);
assert.equal(view.configured, false);
assert.equal(view.rootReadiness[LEGACY_APPDATA_ROOT], 'unavailable');
assert.equal(view.rootReadiness[MANAGED_APPDATA_ROOT], 'unavailable');
assert.equal(view.managedStatus, 'unavailable');
assert.equal(view.managedCapabilityValid, false);
});
test('readiness and saved selection fail closed when root evidence or acknowledgement contradicts', () => {
const unavailableManagedRoot = buildEnrollmentStorageView(baseTrust, {
...baseCapabilities,
availableTrustedAppdataRoots: [
{ root: LEGACY_APPDATA_ROOT, status: 'ready' },
{ root: MANAGED_APPDATA_ROOT, status: 'unavailable' },
],
managedStorage: { ...baseCapabilities.managedStorage, status: 'ready' },
});
assert.equal(unavailableManagedRoot.managedStatus, 'unavailable');
assert.equal(unavailableManagedRoot.managedCapabilityValid, false);
const contradictoryManagedAcknowledgement = buildEnrollmentStorageView(baseTrust, {
...baseCapabilities,
managedStorage: { ...baseCapabilities.managedStorage, backupAcknowledged: false },
});
assert.equal(contradictoryManagedAcknowledgement.configured, false);
assert.equal(contradictoryManagedAcknowledgement.currentRoot, null);
assert.equal(contradictoryManagedAcknowledgement.trustStatus, 'unknown');
assert.equal(contradictoryManagedAcknowledgement.managedStatus, 'unavailable');
const malformedRootEvidence = buildEnrollmentStorageView(baseTrust, {
...baseCapabilities,
availableTrustedAppdataRoots: [{ root: LEGACY_APPDATA_ROOT, status: 'ready' }],
managedStorage: { ...baseCapabilities.managedStorage, status: 'ready' },
});
assert.equal(malformedRootEvidence.managedStatus, 'unavailable');
});
test('managed-root choice requires explicit backup acknowledgement and sends only the two contract fields', () => {
assert.equal(buildStorageRootSelection(MANAGED_APPDATA_ROOT, false), null);
assert.deepEqual(buildStorageRootSelection(MANAGED_APPDATA_ROOT, true), {
trusted_appdata_root: MANAGED_APPDATA_ROOT,
managed_appdata_backup_acknowledged: true,
});
assert.deepEqual(buildStorageRootSelection(LEGACY_APPDATA_ROOT, true), {
trusted_appdata_root: LEGACY_APPDATA_ROOT,
managed_appdata_backup_acknowledged: false,
});
});
test('a failed refresh disables a dirty storage-root draft from being saved', () => {
const gate = {
canManage: true,
configured: true,
payloadAvailable: true,
dirty: true,
loadError: '',
refreshing: false,
saving: false,
initializing: false,
};
assert.equal(canSaveStorageRootSelection(gate), true);
assert.equal(canSaveStorageRootSelection({ ...gate, loadError: 'Refresh failed; showing last-known configuration.' }), false);
assert.equal(canSaveStorageRootSelection({ ...gate, refreshing: true }), false);
assert.equal(canSaveStorageRootSelection({ ...gate, initializing: true }), false);
});
test('initialization requires selected managed root, capability evidence, exact high-risk action and allowed manual policy', () => {
const view = buildEnrollmentStorageView(baseTrust, baseCapabilities);
const preview = {
action: MANAGED_STORAGE_INITIALIZE_ACTION,
target: MANAGED_STORAGE_TARGET,
risk: 'high',
policyDecision: 'allowed',
};
assert.equal(canInitializeManagedStorage(view, preview), true);
assert.equal(canInitializeManagedStorage(view, { ...preview, policyDecision: 'blocked' }), false);
assert.equal(canInitializeManagedStorage(view, { ...preview, target: 'tower/other' }), false);
assert.equal(canInitializeManagedStorage(view, { ...preview, risk: 'low' }), false);
assert.equal(canInitializeManagedStorage(view, { ...view, policyDecision: 'allowed' }), false);
assert.equal(canInitializeManagedStorage(
buildEnrollmentStorageView({ ...baseTrust, managedAppdataBackupAcknowledged: false }, baseCapabilities),
preview,
), false);
assert.equal(canInitializeManagedStorage(
buildEnrollmentStorageView(baseTrust, { ...baseCapabilities, managedStorage: { ...baseCapabilities.managedStorage, status: 'ready' } }),
preview,
), false);
});
test('initialization stays disabled during stale refresh, conflict recovery, dirty drafts and mutations', () => {
const view = buildEnrollmentStorageView(baseTrust, baseCapabilities);
const gate = {
canManage: true,
view,
preview: {
action: MANAGED_STORAGE_INITIALIZE_ACTION,
target: MANAGED_STORAGE_TARGET,
risk: 'high',
policyDecision: 'allowed',
},
dirty: false,
loadError: '',
conflict: '',
refreshing: false,
saving: false,
initializing: false,
};
assert.equal(canRequestManagedStorageInitialization(gate), true);
assert.equal(canRequestManagedStorageInitialization({ ...gate, loadError: 'Refresh failed; showing last known data.' }), false);
assert.equal(canRequestManagedStorageInitialization({ ...gate, conflict: 'The saved selection changed.' }), false);
assert.equal(canRequestManagedStorageInitialization({ ...gate, dirty: true }), false);
assert.equal(canRequestManagedStorageInitialization({ ...gate, refreshing: true }), false);
assert.equal(canRequestManagedStorageInitialization({ ...gate, saving: true }), false);
assert.equal(canRequestManagedStorageInitialization({ ...gate, initializing: true }), false);
assert.equal(canRequestManagedStorageInitialization({ ...gate, canManage: false }), false);
});
test('malformed runtime policy preview is rejected before UI uses its arrays or text', () => {
assert.equal(normalizeManagedStoragePreview({
action: MANAGED_STORAGE_INITIALIZE_ACTION,
target: MANAGED_STORAGE_TARGET,
risk: 'high',
policyDecision: 'allowed',
auditPreview: 'Initialize managed storage',
affectedApps: [],
dependencies: [],
preChecks: 'not-an-array',
postChecks: [],
}), null);
assert.equal(normalizeManagedStoragePreview({
action: MANAGED_STORAGE_INITIALIZE_ACTION,
target: MANAGED_STORAGE_TARGET,
risk: 'high',
policyDecision: 'allowed',
auditPreview: 42,
affectedApps: [],
dependencies: [],
preChecks: [],
postChecks: [],
}), null);
});
test('malformed initializer results never produce a success notice or stringify arbitrary messages', () => {
const malformedResults: unknown[] = [
{ success: true, jobId: {}, auditId: 'audit-1', message: 'Started' },
{ success: true, jobId: 'job-1', auditId: ' ', message: 'Started' },
{ success: true, jobId: `${' '.repeat(201)}job-1`, auditId: 'audit-1', message: 'Started' },
{ success: true, jobId: 'job-1', auditId: `${' '.repeat(201)}audit-1`, message: 'Started' },
{ success: true, jobId: 'job-1', auditId: 'audit-1', message: { detail: 'Started' } },
{ success: true, jobId: 'job-1', auditId: 'audit-1' },
{ success: 'true', jobId: 'job-1', auditId: 'audit-1', message: 'Started' },
{ success: false, message: { detail: 'Denied' } },
];
for (const result of malformedResults) {
assert.deepEqual(normalizeManagedStorageActionOutcome(result), {
tone: 'alert',
message: 'Het initialisatieverzoek is niet bevestigd met geldige referenties.',
});
}
assert.deepEqual(normalizeManagedStorageActionOutcome({
success: true,
jobId: 'job-123',
auditId: 'audit-456',
message: 'Accepted',
}), {
tone: 'status',
message: 'Initialisatieverzoek geregistreerd. Job job-123; audit audit-456. De opslag wordt pas als gereed getoond nadat de controller dat bevestigt.',
});
});
+277
View File
@@ -0,0 +1,277 @@
import type {
PreflightPreview,
EnrollmentStorageRootSelection,
ManagedStorageStatus,
TrustedAppdataRoot,
TrustedAppdataRootReadinessStatus,
} from '@/types/appops';
export const LEGACY_APPDATA_ROOT: TrustedAppdataRoot = '/srv/example/appdata';
export const MANAGED_APPDATA_ROOT: TrustedAppdataRoot = '/var/lib/docker/volumes/itworx-managed-appdata/_data';
export const MANAGED_STORAGE_INITIALIZE_ACTION = 'controller.managed-storage.initialize';
export const MANAGED_STORAGE_TARGET = 'tower/deployment-controller';
export interface EnrollmentStorageView {
configured: boolean;
trustStatus: 'ready' | 'blocked' | 'needs_setup' | 'unknown';
currentRoot: TrustedAppdataRoot | null;
backupAcknowledged: boolean;
rootReadiness: Record<TrustedAppdataRoot, TrustedAppdataRootReadinessStatus>;
managedStatus: ManagedStorageStatus;
managedBlocker: string | null;
managedCapabilityValid: boolean;
}
const isRecord = (value: unknown): value is Record<string, unknown> => (
typeof value === 'object' && value !== null && !Array.isArray(value)
);
const isRoot = (value: unknown): value is TrustedAppdataRoot => (
value === LEGACY_APPDATA_ROOT || value === MANAGED_APPDATA_ROOT
);
const isRootReadiness = (value: unknown): value is TrustedAppdataRootReadinessStatus => (
value === 'ready' || value === 'needs_initialization' || value === 'unavailable'
);
const isManagedStatus = (value: unknown): value is ManagedStorageStatus => (
value === 'not_selected' || value === 'blocked' || value === 'ready' || value === 'initialization_required' || value === 'unavailable'
);
export const buildEnrollmentStorageView = (trust: unknown, capabilities: unknown): EnrollmentStorageView => {
const safeTrust = isRecord(trust) ? trust : {};
const safeCapabilities = isRecord(capabilities) ? capabilities : {};
const trustedRoot = isRoot(safeTrust.trustedAppdataRoot) ? safeTrust.trustedAppdataRoot : null;
const managed = isRecord(safeCapabilities.managedStorage) ? safeCapabilities.managedStorage : null;
const reportedRoots = safeCapabilities.availableTrustedAppdataRoots;
let rootReadiness: Record<TrustedAppdataRoot, TrustedAppdataRootReadinessStatus> = {
[LEGACY_APPDATA_ROOT]: 'unavailable',
[MANAGED_APPDATA_ROOT]: 'unavailable',
};
let rootsValid = false;
if (Array.isArray(reportedRoots) && reportedRoots.length === 2) {
const entries = new Map<TrustedAppdataRoot, TrustedAppdataRootReadinessStatus>();
const valid = reportedRoots.every((entry) => {
if (!isRecord(entry) || !isRoot(entry.root) || !isRootReadiness(entry.status) || entries.has(entry.root)) return false;
entries.set(entry.root, entry.status);
return true;
});
if (valid && entries.has(LEGACY_APPDATA_ROOT) && entries.has(MANAGED_APPDATA_ROOT)) {
rootsValid = true;
rootReadiness = {
[LEGACY_APPDATA_ROOT]: entries.get(LEGACY_APPDATA_ROOT)!,
[MANAGED_APPDATA_ROOT]: entries.get(MANAGED_APPDATA_ROOT)!,
};
}
}
const backupAcknowledged = safeTrust.managedAppdataBackupAcknowledged;
const trustSelectionConsistent = typeof backupAcknowledged === 'boolean' && (
trustedRoot === MANAGED_APPDATA_ROOT
? backupAcknowledged && managed?.root === MANAGED_APPDATA_ROOT && managed.backupAcknowledged === backupAcknowledged
: trustedRoot === LEGACY_APPDATA_ROOT && !backupAcknowledged
);
const managedStatusConsistent = Boolean(
managed && (
(managed.status !== 'ready' || rootReadiness[MANAGED_APPDATA_ROOT] === 'ready') &&
(managed.status !== 'initialization_required' || rootReadiness[MANAGED_APPDATA_ROOT] === 'needs_initialization') &&
(trustedRoot !== MANAGED_APPDATA_ROOT || managed.status !== 'not_selected') &&
(trustedRoot !== MANAGED_APPDATA_ROOT || managed.backupAcknowledged === backupAcknowledged)
)
);
const managedCapabilityValid = Boolean(
rootsValid &&
trustSelectionConsistent &&
managed &&
managed.root === MANAGED_APPDATA_ROOT &&
managed.backupScope === 'dockerRootDir' &&
typeof managed.backupAcknowledged === 'boolean' &&
isManagedStatus(managed.status) &&
managedStatusConsistent,
);
const rawTrustStatus = safeTrust.status === 'ready' || safeTrust.status === 'blocked' || safeTrust.status === 'needs_setup'
? safeTrust.status
: 'unknown';
const configured = safeTrust.configured === true && trustedRoot !== null && trustSelectionConsistent;
const trustStatus = rawTrustStatus === 'needs_setup' || rawTrustStatus === 'blocked'
? rawTrustStatus
: configured && rawTrustStatus === 'ready' ? 'ready' : 'unknown';
return {
configured,
trustStatus,
currentRoot: configured ? trustedRoot : null,
backupAcknowledged: backupAcknowledged === true,
rootReadiness,
managedStatus: managedCapabilityValid ? managed!.status as ManagedStorageStatus : 'unavailable',
managedBlocker: managedCapabilityValid && typeof managed!.blockerCode === 'string' && managed!.blockerCode.length <= 100
? managed!.blockerCode || null
: null,
managedCapabilityValid,
};
};
const isBoundedStringArray = (value: unknown): value is string[] => (
Array.isArray(value) && value.length <= 100 && value.every((item) => typeof item === 'string' && item.length <= 500)
);
export const normalizeManagedStoragePreview = (value: unknown): PreflightPreview | null => {
if (!isRecord(value)) return null;
const rollbackAvailable = value.rollbackAvailable;
if (
typeof value.action !== 'string' || value.action.length > 120 ||
typeof value.target !== 'string' || value.target.length > 200 ||
(value.risk !== 'low' && value.risk !== 'medium' && value.risk !== 'high' && value.risk !== 'critical') ||
(value.policyDecision !== 'allowed' && value.policyDecision !== 'approval_required' && value.policyDecision !== 'blocked') ||
typeof value.auditPreview !== 'string' || value.auditPreview.length > 2000 ||
!isBoundedStringArray(value.affectedApps) ||
!isBoundedStringArray(value.dependencies) ||
!isBoundedStringArray(value.preChecks) ||
!isBoundedStringArray(value.postChecks) ||
(rollbackAvailable !== undefined && typeof rollbackAvailable !== 'boolean')
) return null;
const normalizedRollbackAvailable: boolean | undefined = typeof rollbackAvailable === 'boolean'
? rollbackAvailable
: undefined;
return {
action: value.action,
target: value.target,
risk: value.risk,
policyDecision: value.policyDecision,
auditPreview: value.auditPreview,
affectedApps: value.affectedApps,
dependencies: value.dependencies,
preChecks: value.preChecks,
postChecks: value.postChecks,
...(normalizedRollbackAvailable === undefined ? {} : { rollbackAvailable: normalizedRollbackAvailable }),
};
};
export const buildStorageRootSelection = (
root: TrustedAppdataRoot,
backupAcknowledged: boolean,
): EnrollmentStorageRootSelection | null => {
if (root === MANAGED_APPDATA_ROOT && !backupAcknowledged) return null;
return {
trusted_appdata_root: root,
managed_appdata_backup_acknowledged: root === MANAGED_APPDATA_ROOT,
};
};
export const canInitializeManagedStorage = (
view: EnrollmentStorageView,
preview: unknown,
): boolean => (
view.configured &&
view.currentRoot === MANAGED_APPDATA_ROOT &&
view.backupAcknowledged &&
view.managedCapabilityValid &&
view.managedStatus === 'initialization_required' &&
isRecord(preview) &&
preview.action === MANAGED_STORAGE_INITIALIZE_ACTION &&
preview.target === MANAGED_STORAGE_TARGET &&
preview.risk === 'high' &&
preview.policyDecision === 'allowed'
);
export interface ManagedStorageInitializationGate {
canManage: boolean;
view: EnrollmentStorageView | null | undefined;
preview: unknown;
dirty: boolean;
loadError: string;
conflict: string;
refreshing: boolean;
saving: boolean;
initializing: boolean;
}
export const canRequestManagedStorageInitialization = (gate: ManagedStorageInitializationGate): boolean => (
gate.canManage &&
Boolean(gate.view && canInitializeManagedStorage(gate.view, gate.preview)) &&
!gate.dirty &&
!gate.loadError &&
!gate.conflict &&
!gate.refreshing &&
!gate.saving &&
!gate.initializing
);
export interface StorageRootSaveGate {
canManage: boolean;
configured: boolean;
payloadAvailable: boolean;
dirty: boolean;
loadError: string;
refreshing: boolean;
saving: boolean;
initializing: boolean;
}
export const canSaveStorageRootSelection = (gate: StorageRootSaveGate): boolean => (
gate.canManage &&
gate.configured &&
gate.payloadAvailable &&
gate.dirty &&
!gate.loadError &&
!gate.refreshing &&
!gate.saving &&
!gate.initializing
);
export interface ManagedStorageActionOutcome {
tone: 'status' | 'alert';
message: string;
}
const UNCONFIRMED_INITIALIZATION_MESSAGE = 'Het initialisatieverzoek is niet bevestigd met geldige referenties.';
const isBoundedIdentifier = (value: unknown): value is string => (
typeof value === 'string' && value.trim().length > 0 && value.length <= 200
);
export const normalizeManagedStorageActionOutcome = (value: unknown): ManagedStorageActionOutcome => {
if (!isRecord(value) || typeof value.message !== 'string' || value.message.trim().length === 0 || value.message.length > 500) {
return { tone: 'alert', message: UNCONFIRMED_INITIALIZATION_MESSAGE };
}
if (value.success === true && isBoundedIdentifier(value.jobId) && isBoundedIdentifier(value.auditId)) {
return {
tone: 'status',
message: `Initialisatieverzoek geregistreerd. Job ${value.jobId.trim()}; audit ${value.auditId.trim()}. De opslag wordt pas als gereed getoond nadat de controller dat bevestigt.`,
};
}
if (value.success === false) {
return { tone: 'alert', message: value.message.trim() };
}
return { tone: 'alert', message: UNCONFIRMED_INITIALIZATION_MESSAGE };
};
export const rootReadinessLabel = (status: TrustedAppdataRootReadinessStatus): string => {
if (status === 'ready') return 'Controller confirms ready';
if (status === 'needs_initialization') return 'Controller reports initialization needed';
return 'Not currently confirmed';
};
export const managedStorageStatusLabel = (status: ManagedStorageStatus): string => {
switch (status) {
case 'not_selected': return 'Not selected for future targets';
case 'blocked': return 'Blocked by a required safety condition';
case 'ready': return 'Controller reports ready';
case 'initialization_required': return 'Controller requires one-time initialization';
default: return 'Unavailable or not confirmed';
}
};
export const managedStorageBlockerLabel = (blocker: string | null): string | null => {
switch (blocker) {
case 'managed_appdata_backup_acknowledgement_required': return 'Confirm the Docker-root backup responsibility before continuing.';
case 'managed_appdata_initialization_required': return 'The controller reports that the managed storage volume needs initialization.';
case 'managed_appdata_volume_unavailable': return 'The controller cannot currently verify the managed storage volume.';
default: return blocker ? 'The controller reports an additional storage blocker.' : null;
}
};