From afdaac790003f439a69763d2d883b068e0ef4d92 Mon Sep 17 00:00:00 2001 From: yulia-ivashko Date: Thu, 6 Aug 2026 14:16:02 +0300 Subject: [PATCH] feat: answer whether a workspace still matches the settings in force MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A workspace created under settings that have since changed announced itself only by refusing an operation the operator had already chosen to run. Every fact needed to say so earlier is recorded in the workspace's own metadata, so the refusal was avoidable: the surface could have said which workspace was affected before anyone asked it to do anything. Nothing exposed that cheaply. `inspectWorkspace` answers a related question but runs a health check against the provider, which is far too expensive to do once per row of a list, and the fingerprint comparison folds in each workspace's own image digest, so it cannot be reproduced by comparing a single value elsewhere — reproducing it outside this package would be a second implementation free to drift from this one. `describeWorkspacePolicyState` reads the answer from the record and contacts nothing. --- src/operations.js | 18 ++++++++++++++++++ src/operations.test.js | 18 ++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/src/operations.js b/src/operations.js index 66ccf41..2f11f43 100644 --- a/src/operations.js +++ b/src/operations.js @@ -1,5 +1,6 @@ import { parseProviderKind, parseWorkspaceMetadata, parseWorkspaceRecord } from './contracts.js'; import { readPolicy } from './policy.js'; +import { readMetadata } from './metadata.js'; import { createDockerProvider } from './providers/docker.js'; import { createKubernetesProvider } from './providers/kubernetes.js'; import { createAppleContainerProvider } from './providers/apple-container.js'; @@ -120,6 +121,23 @@ export function createWorkspaceProviderOperations(options = {}) { } return { projectID, workspaces, failures, completeProviders }; }, + /** + * Whether a workspace still matches the settings in force, read from its own + * metadata without contacting the provider. Kept separate from inspectWorkspace, + * which runs a health check: a surface labelling a list must not pay for one probe + * per row, and the answer here is already recorded in the workspace itself. + */ + async describeWorkspacePolicyState(workspace) { + parseWorkspaceRecord(workspace); + const provider = providerForWorkspace(workspace); + try { + readMetadata(workspace, provider.kind, policy); + return { provider: provider.kind, matchesPolicy: true }; + } catch (error) { + if (error?.code === 'WORKSPACE_POLICY_MISMATCH') return { provider: provider.kind, matchesPolicy: false, code: error.code }; + throw error; + } + }, async inspectWorkspace(workspace) { workspace = await adoptWorkspace(workspace); const provider = providerForWorkspace(workspace); diff --git a/src/operations.test.js b/src/operations.test.js index 44fa600..9cd7bc0 100644 --- a/src/operations.test.js +++ b/src/operations.test.js @@ -43,6 +43,24 @@ describe('workspace provider recovery operations', () => { await Promise.all([rm(stateDirectory, { recursive: true, force: true }), rm(sourceDirectory, { recursive: true, force: true })]); }); + it('reads policy state from the workspace itself without contacting the provider', async () => { + const operations = createWorkspaceProviderOperations({ policy, sourceDirectory }); + const workspace = recoveredWorkspace(); + + await expect(operations.describeWorkspacePolicyState(workspace)).resolves.toMatchObject({ matchesPolicy: true }); + // Labelling a list must not cost one provider probe per row. + expect(provider.list).not.toHaveBeenCalled(); + expect(provider.reconcile).not.toHaveBeenCalled(); + }); + + it('reports a workspace created under settings that are no longer in force', async () => { + const operations = createWorkspaceProviderOperations({ policy, sourceDirectory }); + const workspace = recoveredWorkspace(); + const drifted = { ...workspace, extra: { ...workspace.extra, policyFingerprint: 'b'.repeat(64) } }; + + await expect(operations.describeWorkspacePolicyState(drifted)).resolves.toMatchObject({ matchesPolicy: false, code: 'WORKSPACE_POLICY_MISMATCH' }); + }); + function recoveredWorkspace(overrides = {}) { const identity = { provider: 'docker',