@noodleseed/one 0.168.0 → 0.170.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +3 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/capabilities.d.ts +19 -0
- package/dist/commands/capabilities.d.ts.map +1 -0
- package/dist/commands/capabilities.js +128 -0
- package/dist/commands/capabilities.js.map +1 -0
- package/dist/commands/deployment-delete-ops.d.ts +12 -0
- package/dist/commands/deployment-delete-ops.d.ts.map +1 -0
- package/dist/commands/deployment-delete-ops.js +230 -0
- package/dist/commands/deployment-delete-ops.js.map +1 -0
- package/dist/commands/deployment-delete-recovery.d.ts +35 -0
- package/dist/commands/deployment-delete-recovery.d.ts.map +1 -0
- package/dist/commands/deployment-delete-recovery.js +99 -0
- package/dist/commands/deployment-delete-recovery.js.map +1 -0
- package/dist/commands/deployments-ops.d.ts +2 -1
- package/dist/commands/deployments-ops.d.ts.map +1 -1
- package/dist/commands/deployments-ops.js +5 -1
- package/dist/commands/deployments-ops.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/plugin-mode/plugin-operation-contract.d.ts +2 -2
- package/node_modules/@noodle-borg/agent-kit/dist/curated/command-groups.js +4 -0
- package/node_modules/@noodle-borg/agent-kit/dist/generated/example-files.js +1 -1
- package/node_modules/@noodle-borg/agent-kit/dist/generated/surface.js +2 -0
- package/node_modules/@noodle-borg/agent-kit/dist/skill-authoring-refs.js +3 -2
- package/node_modules/@noodle-borg/agent-kit/package.json +1 -1
- package/node_modules/@noodle-borg/assistant-gateway/dist/assistant-interactive.d.ts +1 -0
- package/node_modules/@noodle-borg/assistant-gateway/dist/assistant-interactive.js +4 -1
- package/node_modules/@noodle-borg/authoring/dist/assistant.d.ts +2 -2
- package/node_modules/@noodle-borg/authoring/dist/assistant.js +3 -1
- package/node_modules/@noodle-borg/authoring/dist/index.d.ts +1 -0
- package/node_modules/@noodle-borg/authoring/dist/index.js +1 -0
- package/node_modules/@noodle-borg/authoring/dist/load-authored.js +1 -1
- package/node_modules/@noodle-borg/authoring/dist/recording.d.ts +2 -1
- package/node_modules/@noodle-borg/authoring/dist/recording.js +29 -1
- package/node_modules/@noodle-borg/authoring/dist/server.d.ts +3 -0
- package/node_modules/@noodle-borg/authoring/dist/server.js +5 -1
- package/node_modules/@noodle-borg/authoring/dist/web-capabilities.d.ts +17 -0
- package/node_modules/@noodle-borg/authoring/dist/web-capabilities.js +15 -0
- package/node_modules/@noodle-borg/authoring/package.json +1 -0
- package/node_modules/@noodle-borg/capabilities/dist/index.js +7 -0
- package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-hosted-observability.js +102 -0
- package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-tenant-resources.js +27 -1
- package/node_modules/@noodle-borg/compiler/dist/artifact/assemble.js +3 -0
- package/node_modules/@noodle-borg/compiler/dist/artifact/types.d.ts +2 -0
- package/node_modules/@noodle-borg/compiler/dist/artifact/version.d.ts +2 -1
- package/node_modules/@noodle-borg/compiler/dist/artifact/version.js +2 -1
- package/node_modules/@noodle-borg/compiler/dist/compile.js +2 -0
- package/node_modules/@noodle-borg/compiler/dist/fulfilment-emit.js +18 -3
- package/node_modules/@noodle-borg/compiler/dist/manifest/schema.d.ts +34 -0
- package/node_modules/@noodle-borg/compiler/dist/manifest/schema.js +9 -2
- package/node_modules/@noodle-borg/compiler/dist/web-capabilities.js +55 -0
- package/node_modules/@noodle-borg/compiler/package.json +1 -0
- package/node_modules/@noodle-borg/connector-http/dist/ssrf.js +5 -0
- package/node_modules/@noodle-borg/control-plane/dist/delete-deployment.d.ts +44 -0
- package/node_modules/@noodle-borg/control-plane/dist/delete-deployment.js +105 -0
- package/node_modules/@noodle-borg/control-plane/dist/deployment-deletion-contracts.d.ts +20 -0
- package/node_modules/@noodle-borg/control-plane/dist/portable.d.ts +2 -0
- package/node_modules/@noodle-borg/control-plane/dist/portable.js +1 -0
- package/node_modules/@noodle-borg/knowledge-crawl/dist/bounded-body.js +38 -0
- package/node_modules/@noodle-borg/knowledge-crawl/dist/first-party.js +2 -3
- package/node_modules/@noodle-borg/knowledge-crawl/dist/html-text.js +10 -2
- package/node_modules/@noodle-borg/knowledge-crawl/dist/index.d.ts +1 -0
- package/node_modules/@noodle-borg/knowledge-crawl/dist/index.js +1 -0
- package/node_modules/@noodle-borg/knowledge-crawl/dist/page-reader.d.ts +26 -0
- package/node_modules/@noodle-borg/knowledge-crawl/dist/page-reader.js +127 -0
- package/node_modules/@noodle-borg/knowledge-crawl/dist/robots.js +48 -23
- package/node_modules/@noodle-borg/knowledge-crawl/package.json +1 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/budget.d.ts +29 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/budget.js +124 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/contracts.d.ts +212 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/contracts.js +113 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/errors.d.ts +8 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/errors.js +21 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/executor.d.ts +26 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/executor.js +156 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/limits.d.ts +15 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/limits.js +15 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/operator-contracts.d.ts +159 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/operator-contracts.js +69 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/operator-route.d.ts +5 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/operator-route.js +160 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/policy-store.d.ts +34 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/policy-store.js +61 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/portable.d.ts +10 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/portable.js +10 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/service.d.ts +83 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/service.js +139 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/urls.d.ts +3 -0
- package/node_modules/@noodle-borg/managed-capabilities/dist/urls.js +30 -0
- package/node_modules/@noodle-borg/managed-capabilities/package.json +49 -0
- package/node_modules/@noodle-borg/module/dist/contract.d.ts +11 -0
- package/node_modules/@noodle-borg/runtime/dist/confirmation.js +29 -0
- package/node_modules/@noodle-borg/runtime/dist/connector/types.d.ts +2 -0
- package/node_modules/@noodle-borg/runtime/dist/execute.d.ts +3 -0
- package/node_modules/@noodle-borg/runtime/dist/execute.js +6 -1
- package/node_modules/@noodle-borg/runtime/dist/index.d.ts +2 -1
- package/node_modules/@noodle-borg/runtime/dist/index.js +2 -1
- package/node_modules/@noodle-borg/runtime/dist/interactive.js +10 -1
- package/node_modules/@noodle-borg/runtime/dist/operation-execution.js +3 -0
- package/node_modules/@noodle-borg/runtime/dist/result-meta.d.ts +2 -0
- package/node_modules/@noodle-borg/runtime/dist/result-meta.js +6 -0
- package/node_modules/@noodle-borg/runtime/dist/result.d.ts +4 -0
- package/node_modules/@noodle-borg/runtime/dist/web-capabilities.d.ts +71 -0
- package/node_modules/@noodle-borg/runtime/dist/web-capabilities.js +41 -0
- package/node_modules/@noodle-borg/runtime/package.json +1 -0
- package/node_modules/@noodle-borg/service/dist/deployment-deletion.js +40 -0
- package/node_modules/@noodle-borg/service/dist/local-options.d.ts +1 -0
- package/node_modules/@noodle-borg/service/dist/local-web-capabilities.js +13 -0
- package/node_modules/@noodle-borg/service/dist/mcp-protocol-runtime.js +21 -0
- package/node_modules/@noodle-borg/service/dist/modules/route-dispatch.js +13 -0
- package/node_modules/@noodle-borg/service/dist/registry-compile.js +9 -0
- package/node_modules/@noodle-borg/service/dist/registry-deletion.js +75 -0
- package/node_modules/@noodle-borg/service/dist/registry-state.js +4 -2
- package/node_modules/@noodle-borg/service/dist/registry-targets.js +4 -0
- package/node_modules/@noodle-borg/service/dist/registry-types.d.ts +1 -0
- package/node_modules/@noodle-borg/service/dist/registry.d.ts +2 -0
- package/node_modules/@noodle-borg/service/dist/registry.js +10 -23
- package/node_modules/@noodle-borg/service/dist/routes/assistant-agent.js +5 -2
- package/node_modules/@noodle-borg/service/dist/routes/assistant-interactions.js +7 -4
- package/node_modules/@noodle-borg/service/dist/routes/deploy-dispatch.js +15 -1
- package/node_modules/@noodle-borg/service/dist/routes/deployment-delete.js +53 -0
- package/node_modules/@noodle-borg/service/dist/serve-local.js +14 -0
- package/node_modules/@noodle-borg/service/dist/serve-resource-auth.js +10 -0
- package/node_modules/@noodle-borg/service/dist/service.js +7 -1
- package/node_modules/@noodle-borg/service/dist/store/in-memory.d.ts +2 -1
- package/node_modules/@noodle-borg/service/dist/store/in-memory.js +8 -0
- package/node_modules/@noodle-borg/service/dist/store/json-file-deletion.js +64 -0
- package/node_modules/@noodle-borg/service/dist/store/json-file.d.ts +2 -1
- package/node_modules/@noodle-borg/service/dist/store/json-file.js +23 -5
- package/node_modules/@noodle-borg/service/dist/store.d.ts +5 -1
- package/node_modules/@noodle-borg/service/dist/web-capabilities.js +39 -0
- package/node_modules/@noodle-borg/service/package.json +3 -1
- package/node_modules/@noodle-borg/wire-contracts/dist/deployment-deletion.d.ts +29 -0
- package/node_modules/@noodle-borg/wire-contracts/dist/deployment-deletion.js +33 -0
- package/node_modules/@noodle-borg/wire-contracts/dist/index.d.ts +2 -0
- package/node_modules/@noodle-borg/wire-contracts/dist/index.js +2 -0
- package/node_modules/@noodle-borg/wire-contracts/package.json +1 -0
- package/package.json +3 -2
|
@@ -6,6 +6,7 @@ import type { LocalDevtoolsDelegatedExchangeRuntime } from './local-devtools-del
|
|
|
6
6
|
import type { ServerRegistry } from './registry.js';
|
|
7
7
|
import type { ConfigStore, TenantBridgeAuthConfig } from './store.js';
|
|
8
8
|
type LocalRuntimeOptions = {
|
|
9
|
+
readonly capabilities?: import('@noodle-borg/managed-capabilities').CapabilityService;
|
|
9
10
|
readonly assistantStore?: import('@noodle-borg/assistant-gateway/portable').AssistantStore;
|
|
10
11
|
readonly assistantAppearance?: import('@noodle-borg/assistant-gateway/portable').AssistantAppearanceSettingsStore;
|
|
11
12
|
readonly publicEmbeds?: import('@noodle-borg/assistant-gateway/portable').PublicEmbedStore;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { InMemoryDailyCounterStore } from '@noodle-borg/admission-limits/portable';
|
|
2
|
+
import { PublicPageReader } from '@noodle-borg/knowledge-crawl';
|
|
3
|
+
import { CapabilityService, InMemoryCapabilityPolicyStore, } from '@noodle-borg/managed-capabilities';
|
|
4
|
+
/** Loopback-only composition. Keep PostgreSQL imports out of the published CLI graph. */
|
|
5
|
+
export function localWebCapabilities() {
|
|
6
|
+
return new CapabilityService({
|
|
7
|
+
profile: 'development',
|
|
8
|
+
policies: new InMemoryCapabilityPolicyStore(),
|
|
9
|
+
counters: new InMemoryDailyCounterStore(),
|
|
10
|
+
reader: new PublicPageReader(),
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=local-web-capabilities.js.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { RequestStateManager, requestStateSecretBox, } from '@noodle-borg/protocol';
|
|
2
|
+
/**
|
|
3
|
+
* Build the fleet-shared request-state manager. Static-key deployments use an HKDF domain-separated key;
|
|
4
|
+
* KMS deployments reuse the configured envelope-encryption custodian because its raw KEK cannot be
|
|
5
|
+
* exported for HKDF.
|
|
6
|
+
*/
|
|
7
|
+
export function createHostedMcpRequestStateManager(input) {
|
|
8
|
+
if (input.secretMasterKey !== undefined) {
|
|
9
|
+
return new RequestStateManager(requestStateSecretBox(Buffer.from(input.secretMasterKey, 'base64')));
|
|
10
|
+
}
|
|
11
|
+
return input.secretBox === undefined ? undefined : new RequestStateManager(input.secretBox);
|
|
12
|
+
}
|
|
13
|
+
/** Resolve the temporary origin-wide rollout gate from operator configuration. */
|
|
14
|
+
export function resolveMcpProtocolMode(value) {
|
|
15
|
+
if (value === undefined || value === 'dual')
|
|
16
|
+
return 'dual';
|
|
17
|
+
if (value === 'legacy-only')
|
|
18
|
+
return value;
|
|
19
|
+
throw new Error('NOODLE_MCP_PROTOCOL_MODE must be dual or legacy-only');
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=mcp-protocol-runtime.js.map
|
|
@@ -14,6 +14,19 @@ export function createModuleRouteContext(hostRequest, deps) {
|
|
|
14
14
|
logger: deps.logger ?? noopModuleLogger,
|
|
15
15
|
controlPlane: deps.gate,
|
|
16
16
|
audit: deps.audit,
|
|
17
|
+
capabilityDeployments: {
|
|
18
|
+
get: async (request, scope) => {
|
|
19
|
+
if (request !== hostRequest || !authorizedOrgs.has(scope.org))
|
|
20
|
+
return undefined;
|
|
21
|
+
const target = await deps.registry.getActiveByTenant(scope);
|
|
22
|
+
if (target?.deploymentId === undefined)
|
|
23
|
+
return undefined;
|
|
24
|
+
return {
|
|
25
|
+
deploymentId: target.deploymentId,
|
|
26
|
+
declarations: target.served.artifact.server.capabilities ?? [],
|
|
27
|
+
};
|
|
28
|
+
},
|
|
29
|
+
},
|
|
17
30
|
platformIdentityRecovery: {
|
|
18
31
|
reconcile: (plan) => deps.registry.reconcilePlatformAccountReset(plan),
|
|
19
32
|
customerAuthRestoreProjections: async (deploymentIds) => (await deps.registry.customerAuthRestoreProjections(deploymentIds)).map((projection) => ({
|
|
@@ -9,10 +9,12 @@ import { ManagedConfigBroker } from './credential-broker.js';
|
|
|
9
9
|
import { deploymentCredentialBrokerOptions } from './credential-broker-options.js';
|
|
10
10
|
import { deploymentRecordVersionError } from './deployment-record-version.js';
|
|
11
11
|
import { normalizePersistedManifestForCompile } from './manifest-normalize.js';
|
|
12
|
+
import { registryRecordStillExists } from './registry-deletion.js';
|
|
12
13
|
import { missingCapabilityErrors, missingSecretErrors, missingVariableErrors, } from './registry-helpers.js';
|
|
13
14
|
import { servedTargetFor } from './registry-targets.js';
|
|
14
15
|
import { createDeploymentStateConnector, } from './state-connector-factory.js';
|
|
15
16
|
import { resolveConfigScope, } from './store.js';
|
|
17
|
+
import { deploymentWebConnector } from './web-capabilities.js';
|
|
16
18
|
/** Reject unsupported persisted semantics before constructing executable runtime dependencies. */
|
|
17
19
|
export async function compilePersistedRegistryRecord(record, compileTarget) {
|
|
18
20
|
const versionError = deploymentRecordVersionError(record);
|
|
@@ -196,11 +198,13 @@ export async function compileRegistryTarget(context, input) {
|
|
|
196
198
|
artifact,
|
|
197
199
|
...(boundDeploymentId === undefined ? {} : { deploymentId: boundDeploymentId }),
|
|
198
200
|
});
|
|
201
|
+
const webConnector = deploymentWebConnector(artifact, tenant, boundDeploymentId, context.capabilities);
|
|
199
202
|
return {
|
|
200
203
|
artifact,
|
|
201
204
|
deps: {
|
|
202
205
|
connectors: new InMemoryConnectorRegistry([
|
|
203
206
|
...context.platformConnectors,
|
|
207
|
+
...(webConnector === undefined ? [] : [webConnector]),
|
|
204
208
|
...(nativeRecords === undefined ? [] : [nativeRecords]),
|
|
205
209
|
...(stateConnector !== undefined ? [stateConnector] : []),
|
|
206
210
|
...httpConnectors,
|
|
@@ -252,6 +256,11 @@ export async function loadPersistedRegistryTarget(source, context) {
|
|
|
252
256
|
if (record.active &&
|
|
253
257
|
(await context.hasCustomerAuthConflict(record, built.served.artifact.server.auth)))
|
|
254
258
|
return undefined;
|
|
259
|
+
const exists = state.store === undefined
|
|
260
|
+
? state.records.has(deploymentId)
|
|
261
|
+
: await registryRecordStillExists(state, deploymentId);
|
|
262
|
+
if (!exists)
|
|
263
|
+
return undefined;
|
|
255
264
|
const target = servedTargetFor(record, built.served, context.customerVerifierFactory);
|
|
256
265
|
state.servers.set(deploymentId, target);
|
|
257
266
|
state.records.set(deploymentId, record);
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { planDeploymentDeletion } from './deployment-deletion.js';
|
|
2
|
+
import { targetForPersistedRecord } from './registry-targets.js';
|
|
3
|
+
import { validateTenantRef } from './store/validate.js';
|
|
4
|
+
export function evictDeletedDeployments(state, ids) {
|
|
5
|
+
for (const id of ids) {
|
|
6
|
+
state.records.delete(id);
|
|
7
|
+
state.servers.delete(id);
|
|
8
|
+
}
|
|
9
|
+
for (const [key, id] of state.activeTenants)
|
|
10
|
+
if (ids.has(id))
|
|
11
|
+
state.activeTenants.delete(key);
|
|
12
|
+
}
|
|
13
|
+
export async function deleteRegistryDeployments(state, ref, selection) {
|
|
14
|
+
const safe = validateTenantRef(ref);
|
|
15
|
+
const result = state.store === undefined
|
|
16
|
+
? planDeploymentDeletion([...state.records.values()], safe, selection)
|
|
17
|
+
: await state.store.deleteDeployments(safe, selection);
|
|
18
|
+
if (result.ok)
|
|
19
|
+
evictDeletedDeployments(state, new Set(result.deleted.map((record) => record.deploymentId)));
|
|
20
|
+
return result;
|
|
21
|
+
}
|
|
22
|
+
/** Async compilation must rejoin authority before publishing a result into the disposable cache. */
|
|
23
|
+
export async function registryRecordStillExists(state, deploymentId) {
|
|
24
|
+
const current = state.store === undefined
|
|
25
|
+
? state.records.get(deploymentId)
|
|
26
|
+
: await state.store.get(deploymentId);
|
|
27
|
+
if (current !== undefined && current.archivedAt === undefined)
|
|
28
|
+
return true;
|
|
29
|
+
evictDeletedDeployments(state, new Set([deploymentId]));
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
/** Refresh warmed cache entries from authority and coalesce compilation on a cache miss. */
|
|
33
|
+
export async function readRegistryTarget(state, deploymentId, inflight, targetForRecord, load) {
|
|
34
|
+
if (state.records.get(deploymentId)?.archivedAt !== undefined)
|
|
35
|
+
return undefined;
|
|
36
|
+
if (state.servers.has(deploymentId)) {
|
|
37
|
+
const record = state.store
|
|
38
|
+
? await state.store.get(deploymentId)
|
|
39
|
+
: state.records.get(deploymentId);
|
|
40
|
+
if (record === undefined)
|
|
41
|
+
evictDeletedDeployments(state, new Set([deploymentId]));
|
|
42
|
+
return record === undefined || record.archivedAt !== undefined
|
|
43
|
+
? undefined
|
|
44
|
+
: targetForRecord(record);
|
|
45
|
+
}
|
|
46
|
+
const pending = inflight.get(deploymentId);
|
|
47
|
+
if (pending)
|
|
48
|
+
return pending;
|
|
49
|
+
const promise = load(deploymentId).finally(() => {
|
|
50
|
+
inflight.delete(deploymentId);
|
|
51
|
+
});
|
|
52
|
+
inflight.set(deploymentId, promise);
|
|
53
|
+
return promise;
|
|
54
|
+
}
|
|
55
|
+
/** No-store records are authority, so stale reconciliation must never repopulate absent records. */
|
|
56
|
+
export async function reconcileRegistryTarget(state, record, context) {
|
|
57
|
+
let loaded = false;
|
|
58
|
+
const target = await targetForPersistedRecord(record, {
|
|
59
|
+
...context,
|
|
60
|
+
load: () => {
|
|
61
|
+
loaded = true;
|
|
62
|
+
return context.load();
|
|
63
|
+
},
|
|
64
|
+
records: state.records,
|
|
65
|
+
servers: state.servers,
|
|
66
|
+
recordStillPresent: () => state.store !== undefined || state.records.has(record.deploymentId),
|
|
67
|
+
});
|
|
68
|
+
// A cold load already checks store authority just before publication; warm reconciliation must too.
|
|
69
|
+
// No async presence snapshot in no-store mode: deletion and publication share one synchronous turn.
|
|
70
|
+
const exists = state.store === undefined
|
|
71
|
+
? state.records.has(record.deploymentId)
|
|
72
|
+
: loaded || (await registryRecordStillExists(state, record.deploymentId));
|
|
73
|
+
return exists ? target : undefined;
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=registry-deletion.js.map
|
|
@@ -166,8 +166,10 @@ export async function setRegistryDeploymentLock(state, ref, serverVersion, expec
|
|
|
166
166
|
state.records.set(result.record.deploymentId, result.record);
|
|
167
167
|
return result;
|
|
168
168
|
}
|
|
169
|
-
const
|
|
170
|
-
|
|
169
|
+
const observed = await activeRecordVersion(state, safe, safeVersion);
|
|
170
|
+
// The lookup yields; a concurrent deletion or pointer move must win before any cache write.
|
|
171
|
+
const active = observed === undefined ? undefined : state.records.get(observed.deploymentId);
|
|
172
|
+
if (active === undefined || !active.active || active.archivedAt !== undefined)
|
|
171
173
|
return { ok: false, reason: 'no_active_deployment' };
|
|
172
174
|
if (active.deploymentId !== expectedDeploymentId)
|
|
173
175
|
return { ok: false, reason: 'conflict' };
|
|
@@ -110,6 +110,8 @@ function bindAppPackageSnapshot(served, value) {
|
|
|
110
110
|
}
|
|
111
111
|
/** Reconcile one persisted record with its cached served target without trusting stale auth projections. */
|
|
112
112
|
export async function targetForPersistedRecord(record, state) {
|
|
113
|
+
if (state.recordStillPresent?.() === false)
|
|
114
|
+
return undefined;
|
|
113
115
|
const cached = state.servers.get(record.deploymentId);
|
|
114
116
|
const cachedSchemaVersion = cached === undefined ? undefined : targetPolicyVersions.get(cached);
|
|
115
117
|
state.records.set(record.deploymentId, record);
|
|
@@ -127,6 +129,8 @@ export async function targetForPersistedRecord(record, state) {
|
|
|
127
129
|
(await state.hasCustomerAuthConflict(record, cached.served.artifact.server.auth))) {
|
|
128
130
|
return undefined;
|
|
129
131
|
}
|
|
132
|
+
if (state.recordStillPresent?.() === false)
|
|
133
|
+
return undefined;
|
|
130
134
|
if (cachedSchemaVersion === record.schemaVersion && servedTargetMatchesRecord(cached, record))
|
|
131
135
|
return cached;
|
|
132
136
|
const reconciled = servedTargetFor(record, cached.served, state.customerVerifierFactory);
|
|
@@ -96,6 +96,7 @@ export interface AccessUpdateOptions {
|
|
|
96
96
|
readonly serverVersion?: string | undefined;
|
|
97
97
|
}
|
|
98
98
|
export interface ServerRegistryOptions {
|
|
99
|
+
readonly capabilities?: import('@noodle-borg/managed-capabilities').CapabilityService;
|
|
99
100
|
readonly nativeRecords?: NativeRecordConnectorFactory;
|
|
100
101
|
/** Pure renderer injection used for deployment-bound package construction and failure testing. */
|
|
101
102
|
readonly renderAppPackage?: AppPackageRenderer;
|
|
@@ -9,6 +9,7 @@ import type { ServedTarget } from '@noodle-borg/transport-http';
|
|
|
9
9
|
import type { NativeRecordConnectorFactory } from './native-record-connector.js';
|
|
10
10
|
import { type ActiveDeployProvenance } from './registry-helpers.js';
|
|
11
11
|
import type { AccessUpdateOptions, AccessUpdateResult, DeployOptions, DeployPreflightResult, RecoverResult, RunDeployResult, ServerRegistryOptions } from './registry-types.js';
|
|
12
|
+
import type { DeploymentDeleteResult, DeploymentDeleteSelection } from './store.js';
|
|
12
13
|
import { type AppArchiveResult, type AppRestoreResult, type AppSummary, type ArtifactStore, type ConfigStore, type CustomerAuthRestoreProjection, type DeploymentListFilter, type DeploymentLock, type DeploymentLockUpdateResult, type DeploymentStatus, type DeploymentSummary, type DeployRecord, type EnvSummary, type ProductionEnvironmentChange, type TenantRef } from './store.js';
|
|
13
14
|
export type { RollbackResult } from '@noodle-borg/control-plane/portable';
|
|
14
15
|
export type { DeploymentPackage } from './registry-package.js';
|
|
@@ -29,6 +30,7 @@ export declare class ServerRegistry {
|
|
|
29
30
|
/** Read-only deploy validation used by the CLI before config writes, asset upload, or persistence. */
|
|
30
31
|
preflightDeploy(tenant: TenantRef, manifest: string, options?: DeployOptions): Promise<DeployPreflightResult>;
|
|
31
32
|
recover(): Promise<RecoverResult>;
|
|
33
|
+
deleteDeployments(ref: TenantRef, selection: DeploymentDeleteSelection): Promise<DeploymentDeleteResult>;
|
|
32
34
|
get(deploymentId: string): Promise<ServedTarget | undefined>;
|
|
33
35
|
/** Resolve a deployment-id data-plane route only while that exact record is actively serving. */
|
|
34
36
|
getServing(deploymentId: string): Promise<ServedTarget | undefined>;
|
|
@@ -6,6 +6,7 @@ import { DeploymentPolicyChangedError, UnsupportedDeploymentRecordVersionError,
|
|
|
6
6
|
import { defaultActiveRecord } from './deployment-versioning.js';
|
|
7
7
|
import { updateRegistryAccess } from './registry-access.js';
|
|
8
8
|
import { compilePersistedRegistryRecord, compileRegistryTarget, loadPersistedRegistryTarget, } from './registry-compile.js';
|
|
9
|
+
import { deleteRegistryDeployments, readRegistryTarget, reconcileRegistryTarget, } from './registry-deletion.js';
|
|
9
10
|
import { createRegistryDeployRecord, deployedRecordResult, deploymentWriteVersionError, preflightRegistryDeploy, replacementDeploymentPolicy, resolveDeployAttempt, withDeploymentConfiguration, } from './registry-deploy-transaction.js';
|
|
10
11
|
import { deploymentOwnerSubject } from './registry-helpers.js';
|
|
11
12
|
import { registryDeploymentPackage, renderDeploymentPackageSnapshot } from './registry-package.js';
|
|
@@ -13,7 +14,7 @@ import { recoverRegistryRecords } from './registry-recover.js';
|
|
|
13
14
|
import { rollbackDeployment, rollbackWithMappedErrors } from './registry-rollback.js';
|
|
14
15
|
import { activeRecord, activeRecordVersion, persistDeployRecord, reconcilePlatformAccountResetRegistryCache, registryAppArchivedAt, registryArchiveApp, registryCustomerAuthRestoreProjections, registryGetApp, registryGetDeployment, registryGetEnvironment, registryListApps, registryListEnvironments, registryRestoreApp, registrySetProductionEnvironment, registrySweepArchived, setRegistryDeploymentLock, } from './registry-state.js';
|
|
15
16
|
import { deploymentStatusFor } from './registry-status.js';
|
|
16
|
-
import { deploymentSourceFor, rebindNativeRecords, servedTargetFor,
|
|
17
|
+
import { deploymentSourceFor, rebindNativeRecords, servedTargetFor, tenantDeploymentKey, tenantKey, } from './registry-targets.js';
|
|
17
18
|
import { withBuiltinStateCatalog } from './state-catalog.js';
|
|
18
19
|
import { deploymentSummary, matchesDeploymentFilter, validateDeploymentListFilter, } from './store/records.js';
|
|
19
20
|
import { InMemoryConfigStore, validateTenantRef, } from './store.js';
|
|
@@ -31,6 +32,7 @@ export class ServerRegistry {
|
|
|
31
32
|
#platformCatalog;
|
|
32
33
|
#platformConnectors;
|
|
33
34
|
#nativeRecords;
|
|
35
|
+
#capabilities;
|
|
34
36
|
#stateHandleStoreFactory;
|
|
35
37
|
#delegatedCredentialStore;
|
|
36
38
|
#sealCustomerCredential;
|
|
@@ -60,6 +62,7 @@ export class ServerRegistry {
|
|
|
60
62
|
this.#platformCatalog = withBuiltinStateCatalog(options.platformCatalog ?? []);
|
|
61
63
|
this.#platformConnectors = options.platformConnectors ?? [];
|
|
62
64
|
this.#nativeRecords = options.nativeRecords;
|
|
65
|
+
this.#capabilities = options.capabilities;
|
|
63
66
|
this.#stateHandleStoreFactory = options.stateHandleStoreFactory;
|
|
64
67
|
this.#delegatedCredentialStore = options.delegatedCredentialStore;
|
|
65
68
|
this.#sealCustomerCredential = options.sealCustomerCredential;
|
|
@@ -310,6 +313,7 @@ export class ServerRegistry {
|
|
|
310
313
|
stateHandleStoreFactory: this.#stateHandleStoreFactory,
|
|
311
314
|
platformConnectors: this.#platformConnectors,
|
|
312
315
|
nativeRecords: this.#nativeRecords,
|
|
316
|
+
capabilities: this.#capabilities,
|
|
313
317
|
policyGate: this.#policyGate,
|
|
314
318
|
appPackageRenderer: this.#appPackageRenderer,
|
|
315
319
|
knowledgeSearch: this.#knowledgeSearch,
|
|
@@ -318,26 +322,11 @@ export class ServerRegistry {
|
|
|
318
322
|
#compilePersistedRecord(record) {
|
|
319
323
|
return compilePersistedRegistryRecord(record, this.#compileTarget.bind(this));
|
|
320
324
|
}
|
|
325
|
+
deleteDeployments(ref, selection) {
|
|
326
|
+
return deleteRegistryDeployments(this.#stateView(), ref, selection);
|
|
327
|
+
}
|
|
321
328
|
async get(deploymentId) {
|
|
322
|
-
|
|
323
|
-
return undefined;
|
|
324
|
-
const cached = this.#servers.get(deploymentId);
|
|
325
|
-
if (cached) {
|
|
326
|
-
const record = this.#store
|
|
327
|
-
? await this.#store.get(deploymentId)
|
|
328
|
-
: this.#records.get(deploymentId);
|
|
329
|
-
return record === undefined || record.archivedAt !== undefined
|
|
330
|
-
? undefined
|
|
331
|
-
: this.#targetForPersistedRecord(record);
|
|
332
|
-
}
|
|
333
|
-
const inflight = this.#inflight.get(deploymentId);
|
|
334
|
-
if (inflight)
|
|
335
|
-
return inflight;
|
|
336
|
-
const promise = this.#loadAndCompile(deploymentId).finally(() => {
|
|
337
|
-
this.#inflight.delete(deploymentId);
|
|
338
|
-
});
|
|
339
|
-
this.#inflight.set(deploymentId, promise);
|
|
340
|
-
return promise;
|
|
329
|
+
return readRegistryTarget(this.#stateView(), deploymentId, this.#inflight, (record) => this.#targetForPersistedRecord(record), (id) => this.#loadAndCompile(id));
|
|
341
330
|
}
|
|
342
331
|
/** Resolve a deployment-id data-plane route only while that exact record is actively serving. */
|
|
343
332
|
async getServing(deploymentId) {
|
|
@@ -499,9 +488,7 @@ export class ServerRegistry {
|
|
|
499
488
|
return this.#knowledgeSearch;
|
|
500
489
|
}
|
|
501
490
|
async #targetForPersistedRecord(record) {
|
|
502
|
-
return
|
|
503
|
-
records: this.#records,
|
|
504
|
-
servers: this.#servers,
|
|
491
|
+
return reconcileRegistryTarget(this.#stateView(), record, {
|
|
505
492
|
...(this.#customerVerifierFactory
|
|
506
493
|
? { customerVerifierFactory: this.#customerVerifierFactory }
|
|
507
494
|
: {}),
|
|
@@ -3,6 +3,7 @@ import { assistantCoreModelMessages, assistantTurnModelContextMessages, requestA
|
|
|
3
3
|
import { assistantGuideModelContext, assistantModelToolOncePerSession, assistantModelToolRequiredWhenVisible, assistantOmittedToolResult, assistantViewAvailableData, dispatchAssistantTool, projectAssistantGuide, publicSurfaceOf, recoverableAssistantView, remainingTurnTokens, selectAssistantModelTools, toolTouchesDelegatedAuth, withAssistantSessionExecutionAuthority, } from '@noodle-borg/assistant-gateway/portable';
|
|
4
4
|
import { validateJsonSchemaWithDefaults } from '@noodle-borg/compiler';
|
|
5
5
|
import { guardedFetch } from '@noodle-borg/connector-http';
|
|
6
|
+
import { CapabilityBudget } from '@noodle-borg/managed-capabilities';
|
|
6
7
|
import { evaluateToolAuthorization } from '@noodle-borg/protocol';
|
|
7
8
|
import { interceptForElevation, offersSignIn } from './assistant-elevation.js';
|
|
8
9
|
import { assistantKnowledgeModelTools, executeAssistantKnowledgeSearch, findAssistantKnowledgeComponent, KNOWLEDGE_CITATION_GUIDANCE, resolveAssistantKnowledge, } from './assistant-knowledge.js';
|
|
@@ -98,6 +99,7 @@ export async function runAgentTurn(target, session, message, context, deps, emit
|
|
|
98
99
|
// Across every step of this turn, not per step: eight tool calls is eight, however the model splits
|
|
99
100
|
// them, or a model that loops one call per step would spend the budget a step at a time.
|
|
100
101
|
let toolCallsThisTurn = 0;
|
|
102
|
+
const capabilityBudget = new CapabilityBudget();
|
|
101
103
|
let omittedToolRecoveries = 0;
|
|
102
104
|
let remainingTokens = binding.requestPolicy?.maxTokensPerTurn;
|
|
103
105
|
const turnSignal = binding.requestPolicy?.maxTurnMs === undefined
|
|
@@ -247,7 +249,7 @@ export async function runAgentTurn(target, session, message, context, deps, emit
|
|
|
247
249
|
artifact: target.served.artifact,
|
|
248
250
|
tool,
|
|
249
251
|
arguments: args,
|
|
250
|
-
executeDeps: withAssistantSessionExecutionAuthority(target.served.deps, target.served.artifact, session),
|
|
252
|
+
executeDeps: withAssistantSessionExecutionAuthority({ ...target.served.deps, capabilityBudget }, target.served.artifact, session),
|
|
251
253
|
caller: session.caller,
|
|
252
254
|
context,
|
|
253
255
|
session,
|
|
@@ -273,7 +275,8 @@ export async function runAgentTurn(target, session, message, context, deps, emit
|
|
|
273
275
|
arguments: args,
|
|
274
276
|
}, (failure) => deps.logger?.warn('assistant.view.unresolved', { ...failure }));
|
|
275
277
|
if (view) {
|
|
276
|
-
|
|
278
|
+
if (!dispatch.ephemeral)
|
|
279
|
+
await deps.store.replaceLatestView(session.id, recoverableAssistantView(view));
|
|
277
280
|
emit({ event: 'view_available', data: { ...view } });
|
|
278
281
|
}
|
|
279
282
|
messages.push({
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AssistantInteractionCapacityError, assistantConfirmationReview, assistantConfirmationTransition, assistantInputTransition, assistantInteractionTool, assistantPreparedArgumentReview, assistantPreparedToolContinuation, assistantSafeOutput, assistantToolContinuation, assistantViewAvailableData, auditAssistantInteraction, boundedAssistantExecution, recoverableAssistantView, withAssistantSessionExecutionAuthority, } from '@noodle-borg/assistant-gateway/portable';
|
|
2
|
-
import { executePreparedTool, executeToolInteractive, resumeTool, resumeToolPreparation, } from '@noodle-borg/runtime';
|
|
2
|
+
import { executePreparedTool, executeToolInteractive, hasEphemeralEvidence, resumeTool, resumeToolPreparation, } from '@noodle-borg/runtime';
|
|
3
3
|
import { readJsonBody, sendJson } from '@noodle-borg/transport-http';
|
|
4
4
|
import { applyBrowserCors, authenticateSession, now, } from './assistant.js';
|
|
5
5
|
import { replayOrConflict, writeUnknownOutcome } from './assistant-interaction-replay.js';
|
|
@@ -347,7 +347,9 @@ async function finishExecution(res, deps, session, interaction, context, result,
|
|
|
347
347
|
}
|
|
348
348
|
const completedTool = target.served.artifact.tools.find((tool) => tool.name === toolName);
|
|
349
349
|
const safeOutput = assistantSafeOutput(completedTool?.outputSchema, result.output);
|
|
350
|
-
const
|
|
350
|
+
const ephemeral = hasEphemeralEvidence(result.output);
|
|
351
|
+
const retainedOutput = ephemeral ? { evidenceRetained: false } : safeOutput;
|
|
352
|
+
const completed = await completeAssistantInteractionExecution(deps, session, interaction, 'succeeded', 'tool_completed', toolName, { result: retainedOutput });
|
|
351
353
|
if (!completed)
|
|
352
354
|
return writeUnknownOutcome(res, deps, session, interaction, 'accept');
|
|
353
355
|
await auditAssistantInteraction({
|
|
@@ -364,7 +366,7 @@ async function finishExecution(res, deps, session, interaction, context, result,
|
|
|
364
366
|
// Model-facing scaffolding: the panel saw the tool_completed card, never this row's tool JSON.
|
|
365
367
|
{
|
|
366
368
|
role: 'assistant',
|
|
367
|
-
content: `Completed ${toolName}: ${JSON.stringify(
|
|
369
|
+
content: `Completed ${toolName}: ${JSON.stringify(retainedOutput)}`,
|
|
368
370
|
kind: 'narration',
|
|
369
371
|
},
|
|
370
372
|
]);
|
|
@@ -377,7 +379,8 @@ async function finishExecution(res, deps, session, interaction, context, result,
|
|
|
377
379
|
result: safeOutput,
|
|
378
380
|
}, (failure) => deps.logger?.warn('assistant.view.unresolved', { ...failure }));
|
|
379
381
|
if (view) {
|
|
380
|
-
|
|
382
|
+
if (!ephemeral)
|
|
383
|
+
await deps.store.replaceLatestView(session.id, recoverableAssistantView(view));
|
|
381
384
|
writeViewAvailable(res, view);
|
|
382
385
|
}
|
|
383
386
|
await narrateResolvedInteraction(res, deps, target, session, toolName, 'accept', safeOutput, context, suggestions);
|
|
@@ -2,9 +2,23 @@ import { applySecurityHeaders, enforceHttps, } from '@noodle-borg/transport-http
|
|
|
2
2
|
import { respondRouteError } from '../http-util.js';
|
|
3
3
|
import { handleDeploy } from './control-plane.js';
|
|
4
4
|
import { handleDeployPreflight } from './deploy-preflight.js';
|
|
5
|
+
import { handleDeploymentDelete, parseVersionDeletePath } from './deployment-delete.js';
|
|
5
6
|
import { handleDeploymentLockUpdate } from './deployment-lock.js';
|
|
6
|
-
import { parseTenantDeploymentLockPath, parseTenantDeployPath, parseTenantDeployPreflightPath, } from './paths.js';
|
|
7
|
+
import { parseDeploymentItemPath, parseTenantDeploymentLockPath, parseTenantDeployPath, parseTenantDeployPreflightPath, } from './paths.js';
|
|
7
8
|
export function dispatchDeployRoutes(req, res, url, deps) {
|
|
9
|
+
if (req.method === 'DELETE') {
|
|
10
|
+
const item = parseDeploymentItemPath(url.pathname);
|
|
11
|
+
const deletion = item
|
|
12
|
+
? { kind: 'deployment', ...item }
|
|
13
|
+
: parseVersionDeletePath(url.pathname);
|
|
14
|
+
if (deletion) {
|
|
15
|
+
applySecurityHeaders(res, deps.tls);
|
|
16
|
+
if (enforceHttps(req, res, deps.tls))
|
|
17
|
+
return true;
|
|
18
|
+
handleDeploymentDelete(req, res, deletion, { ...deps, maxBody: deps.maxBody.control }).catch((error) => respondRouteError(deps.logger, res, 'deployment-delete.error', error));
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
8
22
|
const deploymentLock = parseTenantDeploymentLockPath(url.pathname);
|
|
9
23
|
if (req.method === 'PATCH' && deploymentLock !== undefined) {
|
|
10
24
|
applySecurityHeaders(res, deps.tls);
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { deleteDeploymentOperation, } from '@noodle-borg/control-plane/portable';
|
|
2
|
+
import { normalizeServerVersion } from '@noodle-borg/module';
|
|
3
|
+
import { readJsonBody, sendJson } from '@noodle-borg/transport-http';
|
|
4
|
+
import { deploymentDeleteResponseSchema, deploymentVersionDeleteRequestSchema, } from '@noodle-borg/wire-contracts';
|
|
5
|
+
import { validateTenantRef } from '../store.js';
|
|
6
|
+
import { authorizeControlPlane } from './control-plane.js';
|
|
7
|
+
/** An exact numeric version, or the legacy unversioned scope; never semantic-version equivalence. */
|
|
8
|
+
export function parseVersionDeletePath(pathname) {
|
|
9
|
+
const match = /^\/v1\/orgs\/([^/]+)\/apps\/([^/]+)\/envs\/([^/]+)\/versions\/([^/]+)$/.exec(pathname);
|
|
10
|
+
if (!match)
|
|
11
|
+
return undefined;
|
|
12
|
+
try {
|
|
13
|
+
const target = validateTenantRef({
|
|
14
|
+
org: decodeURIComponent(match[1]),
|
|
15
|
+
app: decodeURIComponent(match[2]),
|
|
16
|
+
env: decodeURIComponent(match[3]),
|
|
17
|
+
});
|
|
18
|
+
const version = decodeURIComponent(match[4]);
|
|
19
|
+
return {
|
|
20
|
+
kind: 'version',
|
|
21
|
+
org: target.org,
|
|
22
|
+
target,
|
|
23
|
+
...(version === 'legacy' ? {} : { serverVersion: normalizeServerVersion(version) }),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export async function handleDeploymentDelete(req, res, route, deps) {
|
|
31
|
+
const identity = await authorizeControlPlane(req, res, deps.gate, { requireIdentity: true });
|
|
32
|
+
if (identity === false)
|
|
33
|
+
return;
|
|
34
|
+
let expectedDeploymentIds;
|
|
35
|
+
if (route.kind === 'version') {
|
|
36
|
+
const body = await readJsonBody(req, deps.maxBody);
|
|
37
|
+
if (!body.ok)
|
|
38
|
+
return sendJson(res, body.status, { error: body.error });
|
|
39
|
+
const parsed = deploymentVersionDeleteRequestSchema.safeParse(body.value);
|
|
40
|
+
if (!parsed.success)
|
|
41
|
+
return sendJson(res, 400, { error: 'Invalid version deletion confirmation.' });
|
|
42
|
+
expectedDeploymentIds = parsed.data.expectedDeploymentIds;
|
|
43
|
+
}
|
|
44
|
+
const result = await deleteDeploymentOperation(deps, {
|
|
45
|
+
actor: identity,
|
|
46
|
+
scope: route,
|
|
47
|
+
...(expectedDeploymentIds === undefined ? {} : { expectedDeploymentIds }),
|
|
48
|
+
});
|
|
49
|
+
return result.ok
|
|
50
|
+
? sendJson(res, 200, deploymentDeleteResponseSchema.parse(result.view))
|
|
51
|
+
: sendJson(res, result.status, { code: result.code, error: result.error });
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=deployment-delete.js.map
|
|
@@ -3,6 +3,7 @@ import { InMemoryControlPlaneStore } from '@noodle-borg/control-plane/portable';
|
|
|
3
3
|
import { InMemoryAssetStore } from './assets.js';
|
|
4
4
|
import { createCustomerVerifierFactory, createHostedCustomerVerifierFactory, createLocalDevtoolsCustomerVerifierFactory, } from './customer-verifier.js';
|
|
5
5
|
import { createLocalDevtoolsDelegatedCredentialSource } from './local-devtools-delegated-credentials.js';
|
|
6
|
+
import { localWebCapabilities } from './local-web-capabilities.js';
|
|
6
7
|
import { ServerRegistry } from './registry.js';
|
|
7
8
|
import { isLoopbackHost } from './serve-resource-auth.js';
|
|
8
9
|
import { createServiceHandler } from './service.js';
|
|
@@ -48,7 +49,9 @@ export async function serveLocalService(options = {}) {
|
|
|
48
49
|
const delegatedCredentials = directCustomerAuth
|
|
49
50
|
? createLocalDevtoolsDelegatedCredentialSource()
|
|
50
51
|
: undefined;
|
|
52
|
+
const capabilities = options.runtime?.capabilities ?? localWebCapabilities();
|
|
51
53
|
const registry = new ServerRegistry(undefined, undefined, configStore, {
|
|
54
|
+
capabilities,
|
|
52
55
|
customerVerifierFactory,
|
|
53
56
|
...(delegatedCredentials === undefined
|
|
54
57
|
? {}
|
|
@@ -62,6 +65,17 @@ export async function serveLocalService(options = {}) {
|
|
|
62
65
|
: { localDevtoolsDelegatedExchange: options.localDevtoolsDelegatedExchange }),
|
|
63
66
|
});
|
|
64
67
|
const handler = createServiceHandler(registry, {
|
|
68
|
+
capabilities,
|
|
69
|
+
deployGate: {
|
|
70
|
+
authorize: () => ({
|
|
71
|
+
ok: true,
|
|
72
|
+
identity: {
|
|
73
|
+
subject: 'local-operator',
|
|
74
|
+
email: 'local-operator@localhost',
|
|
75
|
+
superAdmin: true,
|
|
76
|
+
},
|
|
77
|
+
}),
|
|
78
|
+
},
|
|
65
79
|
controlPlaneStore,
|
|
66
80
|
configStore,
|
|
67
81
|
assetStore: new InMemoryAssetStore(),
|
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
import { resolveMcpSubdomainTenant } from '@noodle-borg/control-plane/portable';
|
|
2
2
|
import { normalizePublicBaseDomain, parseCanonicalPublicMcpUrl, parseLegacyTenantMcpPath, } from '@noodle-borg/module';
|
|
3
3
|
import { resolveTenantBridgeAuthVariables } from './managed-config-expressions.js';
|
|
4
|
+
import { createHostedMcpRequestStateManager } from './mcp-protocol-runtime.js';
|
|
4
5
|
import { resolveConfigScope, } from './store.js';
|
|
5
6
|
export function isLoopbackHost(host) {
|
|
6
7
|
return host === '127.0.0.1' || host === '::1' || host === 'localhost';
|
|
7
8
|
}
|
|
9
|
+
export function resolveMcpRequestState(options, secretBox) {
|
|
10
|
+
return (options.mcpRequestState ??
|
|
11
|
+
createHostedMcpRequestStateManager({
|
|
12
|
+
...(options.wrappingMasterKey === undefined && options.secretMasterKey !== undefined
|
|
13
|
+
? { secretMasterKey: options.secretMasterKey }
|
|
14
|
+
: {}),
|
|
15
|
+
...(secretBox === undefined ? {} : { secretBox }),
|
|
16
|
+
}));
|
|
17
|
+
}
|
|
8
18
|
export function assertLocalDevtoolsServiceBoundary(host, options) {
|
|
9
19
|
if (options.localDevtoolsDirectFirebaseAuth === true && !isLoopbackHost(host)) {
|
|
10
20
|
throw new Error('local Devtools Firebase verification requires a loopback service bind');
|
|
@@ -2,6 +2,7 @@ import { InMemoryDailyCounterStore } from '@noodle-borg/admission-limits/portabl
|
|
|
2
2
|
import { InMemoryAssistantAppearanceSettingsStore, InMemoryAssistantStore, } from '@noodle-borg/assistant-gateway/portable';
|
|
3
3
|
import { allowAllGate, InMemoryControlPlaneStore } from '@noodle-borg/control-plane/portable';
|
|
4
4
|
import { dispatchKnowledgeRequest } from '@noodle-borg/knowledge-operations/portable';
|
|
5
|
+
import { capabilityOperatorRoute } from '@noodle-borg/managed-capabilities';
|
|
5
6
|
import { OPENAI_APPS_CHALLENGE_PATH } from '@noodle-borg/module';
|
|
6
7
|
import { applySecurityHeaders, createMcpRouter, enforceHttps, noopLogger, sendJson, } from '@noodle-borg/transport-http';
|
|
7
8
|
import { AnonymousConsumerLimiter, createAdmissionGate } from './admission.js';
|
|
@@ -163,7 +164,12 @@ export function createServiceHandler(registry, options = {}) {
|
|
|
163
164
|
});
|
|
164
165
|
archiveSweeper.maybeSweep();
|
|
165
166
|
const moduleRouteDeps = {
|
|
166
|
-
routes:
|
|
167
|
+
routes: [
|
|
168
|
+
...moduleHost.routes,
|
|
169
|
+
...(options.capabilities === undefined
|
|
170
|
+
? []
|
|
171
|
+
: [capabilityOperatorRoute(options.capabilities)]),
|
|
172
|
+
],
|
|
167
173
|
logger,
|
|
168
174
|
gate,
|
|
169
175
|
controlPlane,
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import type { ActiveAccessUpdateInput, AppArchiveResult, AppRestorePrecondition, AppRestoreResult, AppSummary, ArtifactStore, DeploymentActivationPrecondition, DeploymentActivationResult, DeploymentListFilter, DeploymentLock, DeploymentLockUpdateResult, DeploymentPolicyPrecondition, DeploymentSummary, DeployRecord, EnvSummary, ProductionEnvironmentChange, TenantAuthConfig, TenantRef } from '../store.js';
|
|
1
|
+
import type { ActiveAccessUpdateInput, AppArchiveResult, AppRestorePrecondition, AppRestoreResult, AppSummary, ArtifactStore, DeploymentActivationPrecondition, DeploymentActivationResult, DeploymentDeleteResult, DeploymentDeleteSelection, DeploymentListFilter, DeploymentLock, DeploymentLockUpdateResult, DeploymentPolicyPrecondition, DeploymentSummary, DeployRecord, EnvSummary, ProductionEnvironmentChange, TenantAuthConfig, TenantRef } from '../store.js';
|
|
2
2
|
/** In-memory store: keeps records in a Map. Used by tests and as an explicit, non-persistent option. */
|
|
3
3
|
export declare class InMemoryArtifactStore implements ArtifactStore {
|
|
4
4
|
#private;
|
|
5
|
+
deleteDeployments(ref: TenantRef, selection: DeploymentDeleteSelection): Promise<DeploymentDeleteResult>;
|
|
5
6
|
append(record: DeployRecord, precondition?: DeploymentPolicyPrecondition): Promise<void>;
|
|
6
7
|
loadAll(): Promise<readonly DeployRecord[]>;
|
|
7
8
|
get(deploymentId: string): Promise<DeployRecord | undefined>;
|
|
@@ -2,6 +2,7 @@ import { normalizeServerVersion } from '@noodle-borg/module';
|
|
|
2
2
|
import { assertSameAppPackageSnapshot, sanitizeDeployRecordAppPackageSnapshot, } from '../app-package-snapshot.js';
|
|
3
3
|
import { assertCustomerAuthRestorePrecondition, assertUniqueActiveCustomerAuthAudienceBindings, findActiveCustomerAuthAudienceConflict, requiresCustomerAuthProjection, } from '../customer-auth-audience-binding.js';
|
|
4
4
|
import { matchesDeploymentActivation } from '../deployment-activation-precondition.js';
|
|
5
|
+
import { planDeploymentDeletion } from '../deployment-deletion.js';
|
|
5
6
|
import { assertDeploymentActivationUnlocked, assertDeploymentAppendUnlocked, } from '../deployment-lock.js';
|
|
6
7
|
import { assertDeploymentAppendPolicy, assertDeploymentAppendVersion, } from '../deployment-record-version.js';
|
|
7
8
|
import { defaultActiveRecord, sameDeploymentScope, sameTenantRecord, } from '../deployment-versioning.js';
|
|
@@ -11,6 +12,13 @@ import { validateSlug, validateTenantRef } from './validate.js';
|
|
|
11
12
|
export class InMemoryArtifactStore {
|
|
12
13
|
#records = new Map();
|
|
13
14
|
#productionEnvironments = new Map();
|
|
15
|
+
deleteDeployments(ref, selection) {
|
|
16
|
+
const result = planDeploymentDeletion([...this.#records.values()], ref, selection);
|
|
17
|
+
if (result.ok)
|
|
18
|
+
for (const record of result.deleted)
|
|
19
|
+
this.#records.delete(record.deploymentId);
|
|
20
|
+
return Promise.resolve(result);
|
|
21
|
+
}
|
|
14
22
|
async append(record, precondition) {
|
|
15
23
|
assertDeploymentAppendVersion([...this.#records.values()], record);
|
|
16
24
|
assertDeploymentAppendPolicy([...this.#records.values()], record, precondition);
|