@a5c-ai/krate 5.0.1-staging.00fa5317c
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/Dockerfile +31 -0
- package/README.md +183 -0
- package/bin/krate-demo.mjs +23 -0
- package/bin/krate-server.mjs +14 -0
- package/dist/krate-controller-ui.json +3205 -0
- package/dist/krate-lifecycle.json +201 -0
- package/dist/krate-runtime-snapshot.json +3125 -0
- package/dist/krate-summary.json +724 -0
- package/docs/README.md +61 -0
- package/docs/agents/README.md +83 -0
- package/docs/agents/acceptance-test-matrix.md +193 -0
- package/docs/agents/agent-mux-adapter-contract.md +167 -0
- package/docs/agents/agent-mux-source-map.md +310 -0
- package/docs/agents/agent-run-memory-import-spec.md +256 -0
- package/docs/agents/agent-stack-management-spec.md +421 -0
- package/docs/agents/api-contract-spec.md +309 -0
- package/docs/agents/artifacts-writeback-spec.md +145 -0
- package/docs/agents/chart-packaging-spec.md +128 -0
- package/docs/agents/ci-orchestration-spec.md +140 -0
- package/docs/agents/context-assembly-spec.md +219 -0
- package/docs/agents/controller-reconciliation-spec.md +255 -0
- package/docs/agents/crd-schema-spec.md +315 -0
- package/docs/agents/decision-log-open-questions.md +169 -0
- package/docs/agents/developer-implementation-checklist.md +329 -0
- package/docs/agents/dispatching-design.md +262 -0
- package/docs/agents/gaps-agent-mux-to-krate-crds.md +298 -0
- package/docs/agents/glossary.md +66 -0
- package/docs/agents/implementation-blueprint.md +324 -0
- package/docs/agents/implementation-rollout-slices.md +251 -0
- package/docs/agents/memory-context-integration-spec.md +194 -0
- package/docs/agents/memory-ontology-schema-spec.md +253 -0
- package/docs/agents/memory-operations-runbook.md +121 -0
- package/docs/agents/mvp-vertical-slice-spec.md +146 -0
- package/docs/agents/observability-audit-spec.md +265 -0
- package/docs/agents/operator-runbook.md +174 -0
- package/docs/agents/org-memory-api-payload-examples.md +333 -0
- package/docs/agents/org-memory-controller-sequence-spec.md +181 -0
- package/docs/agents/org-memory-e2e-fixture-plan.md +161 -0
- package/docs/agents/org-memory-ui-implementation-map.md +114 -0
- package/docs/agents/org-memory-vertical-slice-spec.md +168 -0
- package/docs/agents/org-resource-model-delta-spec.md +111 -0
- package/docs/agents/org-route-resource-model-spec.md +183 -0
- package/docs/agents/org-scoping-namespace-spec.md +114 -0
- package/docs/agents/rbac-secrets-management-spec.md +406 -0
- package/docs/agents/repository-page-integration-spec.md +255 -0
- package/docs/agents/resource-contract-examples.md +808 -0
- package/docs/agents/resource-relationship-map.md +190 -0
- package/docs/agents/security-threat-model.md +188 -0
- package/docs/agents/shared-memory-company-brain-spec.md +358 -0
- package/docs/agents/storage-migration-spec.md +168 -0
- package/docs/agents/subagent-orchestration-spec.md +152 -0
- package/docs/agents/system-overview.md +88 -0
- package/docs/agents/tools-mcp-skills-spec.md +189 -0
- package/docs/agents/traceability-matrix.md +79 -0
- package/docs/agents/ui-flow-spec.md +211 -0
- package/docs/agents/ui-ux-system-spec.md +426 -0
- package/docs/agents/workspace-lifecycle-spec.md +166 -0
- package/docs/architecture-spec.md +78 -0
- package/docs/components/control-plane.md +78 -0
- package/docs/components/data-plane.md +69 -0
- package/docs/components/hooks-events.md +67 -0
- package/docs/components/identity-rbac-policy.md +73 -0
- package/docs/components/kubevela-oam.md +70 -0
- package/docs/components/operations-publishing.md +81 -0
- package/docs/components/runners-ci.md +66 -0
- package/docs/components/web-ui.md +94 -0
- package/docs/external/README.md +47 -0
- package/docs/external/bidirectional-sync-design.md +134 -0
- package/docs/external/cicd-interface.md +64 -0
- package/docs/external/external-backend-controllers.md +170 -0
- package/docs/external/external-backend-crds.md +234 -0
- package/docs/external/external-backend-ui-spec.md +151 -0
- package/docs/external/external-backend-ux-flows.md +115 -0
- package/docs/external/external-object-mapping.md +125 -0
- package/docs/external/git-forge-interface.md +68 -0
- package/docs/external/github-integration-design.md +151 -0
- package/docs/external/issue-tracking-interface.md +66 -0
- package/docs/external/provider-capability-manifests.md +204 -0
- package/docs/external/provider-catalog.md +139 -0
- package/docs/external/provider-rollout-testing.md +78 -0
- package/docs/external/research-results.md +48 -0
- package/docs/external/security-auth-permissions.md +81 -0
- package/docs/external/sync-state-machines.md +108 -0
- package/docs/external/unified-external-backend-model.md +107 -0
- package/docs/external/user-facing-changes.md +67 -0
- package/docs/gaps.md +161 -0
- package/docs/install.md +94 -0
- package/docs/krate-design.md +334 -0
- package/docs/local-minikube.md +55 -0
- package/docs/ontology/README.md +32 -0
- package/docs/ontology/bounded-contexts.md +29 -0
- package/docs/ontology/events-and-hooks.md +32 -0
- package/docs/ontology/oam-kubevela.md +32 -0
- package/docs/ontology/operations-and-release.md +25 -0
- package/docs/ontology/personas-and-actors.md +32 -0
- package/docs/ontology/policies-and-invariants.md +33 -0
- package/docs/ontology/problem-space.md +30 -0
- package/docs/ontology/resource-contracts.md +40 -0
- package/docs/ontology/resource-taxonomy.md +42 -0
- package/docs/ontology/runners-and-ci.md +29 -0
- package/docs/ontology/solution-space.md +24 -0
- package/docs/ontology/storage-and-data-boundaries.md +29 -0
- package/docs/ontology/validation-matrix.md +24 -0
- package/docs/ontology/web-ui-excellent-flows.md +32 -0
- package/docs/ontology/workflows.md +39 -0
- package/docs/ontology/world.md +35 -0
- package/docs/openapi.yaml +1275 -0
- package/docs/product-requirements.md +62 -0
- package/docs/roadmap-mvp.md +87 -0
- package/docs/system-requirements.md +90 -0
- package/docs/tests/README.md +53 -0
- package/docs/tests/agent-qa-plan.md +63 -0
- package/docs/tests/browser-ui-tests.md +62 -0
- package/docs/tests/ci-quality-gates.md +48 -0
- package/docs/tests/coverage-model.md +64 -0
- package/docs/tests/e2e-scenario-tests.md +53 -0
- package/docs/tests/fixtures-test-data.md +63 -0
- package/docs/tests/observability-reliability-tests.md +54 -0
- package/docs/tests/product-test-matrix.md +145 -0
- package/docs/tests/qa-adoption-roadmap.md +130 -0
- package/docs/tests/qa-automation-plan.md +101 -0
- package/docs/tests/security-compliance-tests.md +57 -0
- package/docs/tests/test-framework-tools.md +88 -0
- package/docs/tests/test-suite-layout.md +121 -0
- package/docs/tests/unit-integration-tests.md +48 -0
- package/docs/todo-kyverno +714 -0
- package/docs/todos.md +4 -0
- package/docs/user-stories.md +78 -0
- package/examples/minikube-demo.yaml +190 -0
- package/examples/oam-application.yaml +23 -0
- package/examples/policy-kyverno-pr-title.yaml +18 -0
- package/package.json +63 -0
- package/scripts/build.mjs +29 -0
- package/scripts/setup-minikube.mjs +65 -0
- package/scripts/smoke.mjs +37 -0
- package/scripts/validate-doc-coverage.mjs +152 -0
- package/scripts/validate-package.mjs +93 -0
- package/scripts/validate-ui.mjs +278 -0
- package/src/agent-adapter-controller.js +169 -0
- package/src/agent-approval-controller.js +170 -0
- package/src/agent-context-bundles.js +242 -0
- package/src/agent-dispatch-controller.js +209 -0
- package/src/agent-gateway-config-controller.js +147 -0
- package/src/agent-memory-controller.js +357 -0
- package/src/agent-memory-import.js +327 -0
- package/src/agent-memory-query.js +292 -0
- package/src/agent-memory-repository-source-controller.js +255 -0
- package/src/agent-mux-client.js +280 -0
- package/src/agent-permission-review.js +250 -0
- package/src/agent-project-controller.js +117 -0
- package/src/agent-provider-config-controller.js +150 -0
- package/src/agent-secret-config-grant-controller.js +282 -0
- package/src/agent-session-transcript-controller.js +189 -0
- package/src/agent-stack-controller.js +347 -0
- package/src/agent-subagent-controller.js +160 -0
- package/src/agent-transport-binding-controller.js +121 -0
- package/src/agent-trigger-controller.js +381 -0
- package/src/agent-workspace-controller.js +702 -0
- package/src/agent-writeback-controller.js +302 -0
- package/src/api-controller.js +541 -0
- package/src/argocd-gitops.js +43 -0
- package/src/async-controller.js +207 -0
- package/src/audit-controller.js +191 -0
- package/src/auth.js +307 -0
- package/src/component-catalog.js +41 -0
- package/src/control-plane.js +136 -0
- package/src/controller-client.js +72 -0
- package/src/controller-ui.js +617 -0
- package/src/data-plane.js +179 -0
- package/src/event-bus.js +61 -0
- package/src/external/conflict-controller.js +225 -0
- package/src/external/github/auth.js +96 -0
- package/src/external/github/cicd.js +180 -0
- package/src/external/github/git-forge.js +240 -0
- package/src/external/github/index.js +144 -0
- package/src/external/github/issue-tracking.js +163 -0
- package/src/external/provider-adapter.js +161 -0
- package/src/external/provider-resource-factory.js +161 -0
- package/src/external/sync-controller.js +235 -0
- package/src/external/webhook-controller.js +144 -0
- package/src/external/write-controller.js +283 -0
- package/src/gitea-backend.js +131 -0
- package/src/gitea-service.js +173 -0
- package/src/handoff.js +98 -0
- package/src/hooks-events.js +63 -0
- package/src/http-server.js +377 -0
- package/src/identity-policy.js +86 -0
- package/src/index.js +57 -0
- package/src/kubernetes-controller-async.js +511 -0
- package/src/kubernetes-controller.js +878 -0
- package/src/kubernetes-resource-gateway.js +48 -0
- package/src/notification-controller.js +178 -0
- package/src/operations.js +112 -0
- package/src/org-scoping.js +5 -0
- package/src/resource-model.js +221 -0
- package/src/runner-controller.js +272 -0
- package/src/runners-ci.js +48 -0
- package/src/runtime.js +196 -0
- package/src/snapshot-cache.js +157 -0
- package/src/web-ui.js +40 -0
- package/tests/agent-adapter-controller.test.js +361 -0
- package/tests/agent-approval-controller.test.js +173 -0
- package/tests/agent-context-bundles.test.js +278 -0
- package/tests/agent-dispatch-controller.test.js +315 -0
- package/tests/agent-gateway-config-controller.test.js +386 -0
- package/tests/agent-memory-controller.test.js +308 -0
- package/tests/agent-memory-import-snapshot.test.js +477 -0
- package/tests/agent-memory-query.test.js +404 -0
- package/tests/agent-memory-repository-source.test.js +514 -0
- package/tests/agent-mux-client.test.js +204 -0
- package/tests/agent-permission-review-v2.test.js +317 -0
- package/tests/agent-permission-review.test.js +209 -0
- package/tests/agent-project-controller.test.js +302 -0
- package/tests/agent-provider-config-controller.test.js +376 -0
- package/tests/agent-resources.test.js +228 -0
- package/tests/agent-secret-config-grant.test.js +231 -0
- package/tests/agent-session-transcript-controller.test.js +499 -0
- package/tests/agent-stack-controller.test.js +221 -0
- package/tests/agent-subagent-controller.test.js +201 -0
- package/tests/agent-transport-binding-controller.test.js +294 -0
- package/tests/agent-trigger-controller.test.js +211 -0
- package/tests/agent-trigger-routes.test.js +190 -0
- package/tests/agent-trigger-sources.test.js +245 -0
- package/tests/agent-workspace-controller.test.js +181 -0
- package/tests/agent-writeback.test.js +292 -0
- package/tests/approval-persistence.test.js +171 -0
- package/tests/async-controller.test.js +252 -0
- package/tests/audit-controller.test.js +227 -0
- package/tests/codespace-controller.test.js +318 -0
- package/tests/deployment.test.js +407 -0
- package/tests/e2e/lifecycle.test.js +117 -0
- package/tests/event-bus-integration.test.js +190 -0
- package/tests/external-github-forge.test.js +560 -0
- package/tests/external-github-issues-cicd.test.js +520 -0
- package/tests/external-integration.test.js +470 -0
- package/tests/external-persistence.test.js +340 -0
- package/tests/external-provider-adapter.test.js +365 -0
- package/tests/external-resource-model.test.js +215 -0
- package/tests/external-webhook-sync.test.js +287 -0
- package/tests/external-write-conflict.test.js +353 -0
- package/tests/gitea-service.test.js +253 -0
- package/tests/health-check-real.test.js +165 -0
- package/tests/integration/full-flow.test.js +266 -0
- package/tests/krate.test.js +756 -0
- package/tests/memory-search-wiring.test.js +270 -0
- package/tests/notification-controller.test.js +196 -0
- package/tests/notification-integration.test.js +179 -0
- package/tests/org-scoping.test.js +687 -0
- package/tests/runner-controller.test.js +327 -0
- package/tests/runner-integration.test.js +231 -0
- package/tests/session-cookie-hmac.test.js +151 -0
- package/tests/snapshot-performance.test.js +247 -0
- package/tests/sse-events.test.js +107 -0
- package/tests/webhook-trigger.test.js +198 -0
- package/tests/workspace-volumes.test.js +312 -0
- package/tests/writeback-persistence.test.js +207 -0
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import test from 'node:test';
|
|
3
|
+
import {
|
|
4
|
+
createAgentGatewayConfigController,
|
|
5
|
+
validateAgentGatewayConfig,
|
|
6
|
+
createResource,
|
|
7
|
+
AGENT_GATEWAY_CONFIG_CONTROLLER_BOUNDARY
|
|
8
|
+
} from '../src/index.js';
|
|
9
|
+
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
// Acceptance criteria: Slice 1.2e — Agent Gateway Config Controller
|
|
12
|
+
//
|
|
13
|
+
// An AgentGatewayConfig defines runtime gateway settings and feature flags
|
|
14
|
+
// for connecting to the Agent Mux gateway. It specifies the gateway name,
|
|
15
|
+
// org reference, endpoint URL, feature flags, connection pool settings,
|
|
16
|
+
// and TLS configuration reference.
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
|
|
19
|
+
function makeGatewayConfig(name, overrides = {}) {
|
|
20
|
+
return createResource('AgentGatewayConfig', { name, namespace: 'krate-org-default' }, {
|
|
21
|
+
organizationRef: 'default',
|
|
22
|
+
endpointUrl: 'https://agent-mux.example.com/v1',
|
|
23
|
+
...overrides
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
// 1. Factory and shape
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
|
|
31
|
+
test('createAgentGatewayConfigController returns a controller with expected methods', () => {
|
|
32
|
+
const controller = createAgentGatewayConfigController();
|
|
33
|
+
assert.ok(controller, 'controller must be truthy');
|
|
34
|
+
assert.equal(typeof controller.validate, 'function', 'controller must expose validate');
|
|
35
|
+
assert.equal(typeof controller.getEndpointUrl, 'function', 'controller must expose getEndpointUrl');
|
|
36
|
+
assert.equal(typeof controller.getFeatureFlags, 'function', 'controller must expose getFeatureFlags');
|
|
37
|
+
assert.equal(typeof controller.getConnectionPool, 'function', 'controller must expose getConnectionPool');
|
|
38
|
+
assert.equal(typeof controller.getTlsConfigRef, 'function', 'controller must expose getTlsConfigRef');
|
|
39
|
+
assert.equal(controller.role, 'agent-gateway-config-controller', 'controller must declare its role');
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
// 2. validate — happy path
|
|
44
|
+
// ---------------------------------------------------------------------------
|
|
45
|
+
|
|
46
|
+
test('validate accepts a valid gateway config with name, organizationRef, and endpointUrl', () => {
|
|
47
|
+
const controller = createAgentGatewayConfigController();
|
|
48
|
+
const config = makeGatewayConfig('prod-gateway');
|
|
49
|
+
const result = controller.validate(config);
|
|
50
|
+
|
|
51
|
+
assert.equal(result.valid, true, 'valid config must pass validation');
|
|
52
|
+
assert.ok(Array.isArray(result.errors), 'result must contain an errors array');
|
|
53
|
+
assert.equal(result.errors.length, 0, 'errors array must be empty for a valid config');
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// ---------------------------------------------------------------------------
|
|
57
|
+
// 3. validate — missing name
|
|
58
|
+
// ---------------------------------------------------------------------------
|
|
59
|
+
|
|
60
|
+
test('validate rejects config with missing name', () => {
|
|
61
|
+
const controller = createAgentGatewayConfigController();
|
|
62
|
+
const config = {
|
|
63
|
+
apiVersion: 'krate.a5c.ai/v1alpha1',
|
|
64
|
+
kind: 'AgentGatewayConfig',
|
|
65
|
+
metadata: { namespace: 'krate-org-default', labels: {}, annotations: {} },
|
|
66
|
+
spec: { organizationRef: 'default', endpointUrl: 'https://agent-mux.example.com/v1' },
|
|
67
|
+
status: {}
|
|
68
|
+
};
|
|
69
|
+
const result = controller.validate(config);
|
|
70
|
+
|
|
71
|
+
assert.equal(result.valid, false, 'config without a name must fail validation');
|
|
72
|
+
assert.ok(result.errors.length > 0, 'errors array must not be empty');
|
|
73
|
+
assert.ok(
|
|
74
|
+
result.errors.some((e) => /name/i.test(e)),
|
|
75
|
+
'at least one error must mention "name"'
|
|
76
|
+
);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// ---------------------------------------------------------------------------
|
|
80
|
+
// 4. validate — missing endpointUrl
|
|
81
|
+
// ---------------------------------------------------------------------------
|
|
82
|
+
|
|
83
|
+
test('validate rejects config with missing endpointUrl', () => {
|
|
84
|
+
const controller = createAgentGatewayConfigController();
|
|
85
|
+
const config = makeGatewayConfig('no-url-gateway');
|
|
86
|
+
delete config.spec.endpointUrl;
|
|
87
|
+
const result = controller.validate(config);
|
|
88
|
+
|
|
89
|
+
assert.equal(result.valid, false, 'config without endpointUrl must fail validation');
|
|
90
|
+
assert.ok(result.errors.length > 0, 'errors array must not be empty');
|
|
91
|
+
assert.ok(
|
|
92
|
+
result.errors.some((e) => /endpointUrl/i.test(e)),
|
|
93
|
+
'at least one error must mention "endpointUrl"'
|
|
94
|
+
);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// ---------------------------------------------------------------------------
|
|
98
|
+
// 5. validate — invalid endpointUrl protocol
|
|
99
|
+
// ---------------------------------------------------------------------------
|
|
100
|
+
|
|
101
|
+
test('validate rejects config with invalid endpointUrl protocol', () => {
|
|
102
|
+
const controller = createAgentGatewayConfigController();
|
|
103
|
+
const config = makeGatewayConfig('bad-url-gateway', { endpointUrl: 'ftp://agent-mux.example.com' });
|
|
104
|
+
const result = controller.validate(config);
|
|
105
|
+
|
|
106
|
+
assert.equal(result.valid, false, 'config with unsupported URL protocol must fail validation');
|
|
107
|
+
assert.ok(result.errors.length > 0, 'errors array must not be empty');
|
|
108
|
+
assert.ok(
|
|
109
|
+
result.errors.some((e) => /endpointUrl/i.test(e)),
|
|
110
|
+
'at least one error must mention "endpointUrl"'
|
|
111
|
+
);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// ---------------------------------------------------------------------------
|
|
115
|
+
// 6. validate — websocket URL is valid
|
|
116
|
+
// ---------------------------------------------------------------------------
|
|
117
|
+
|
|
118
|
+
test('validate accepts config with wss:// endpoint URL', () => {
|
|
119
|
+
const controller = createAgentGatewayConfigController();
|
|
120
|
+
const config = makeGatewayConfig('ws-gateway', { endpointUrl: 'wss://agent-mux.example.com/connect' });
|
|
121
|
+
const result = controller.validate(config);
|
|
122
|
+
|
|
123
|
+
assert.equal(result.valid, true, 'config with wss:// endpoint must pass validation');
|
|
124
|
+
assert.equal(result.errors.length, 0, 'errors array must be empty');
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
// ---------------------------------------------------------------------------
|
|
128
|
+
// 7. validate — invalid connection pool maxConnections
|
|
129
|
+
// ---------------------------------------------------------------------------
|
|
130
|
+
|
|
131
|
+
test('validate rejects config with non-positive maxConnections', () => {
|
|
132
|
+
const controller = createAgentGatewayConfigController();
|
|
133
|
+
const config = makeGatewayConfig('bad-pool-gateway', { connectionPool: { maxConnections: 0 } });
|
|
134
|
+
const result = controller.validate(config);
|
|
135
|
+
|
|
136
|
+
assert.equal(result.valid, false, 'config with maxConnections=0 must fail validation');
|
|
137
|
+
assert.ok(result.errors.length > 0, 'errors array must not be empty');
|
|
138
|
+
assert.ok(
|
|
139
|
+
result.errors.some((e) => /maxConnections/i.test(e)),
|
|
140
|
+
'at least one error must mention "maxConnections"'
|
|
141
|
+
);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
// ---------------------------------------------------------------------------
|
|
145
|
+
// 8. validate — invalid timeoutMs
|
|
146
|
+
// ---------------------------------------------------------------------------
|
|
147
|
+
|
|
148
|
+
test('validate rejects config with negative timeoutMs', () => {
|
|
149
|
+
const controller = createAgentGatewayConfigController();
|
|
150
|
+
const config = makeGatewayConfig('bad-timeout-gateway', { connectionPool: { timeoutMs: -1 } });
|
|
151
|
+
const result = controller.validate(config);
|
|
152
|
+
|
|
153
|
+
assert.equal(result.valid, false, 'config with negative timeoutMs must fail validation');
|
|
154
|
+
assert.ok(result.errors.length > 0, 'errors array must not be empty');
|
|
155
|
+
assert.ok(
|
|
156
|
+
result.errors.some((e) => /timeoutMs/i.test(e)),
|
|
157
|
+
'at least one error must mention "timeoutMs"'
|
|
158
|
+
);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
// ---------------------------------------------------------------------------
|
|
162
|
+
// 9. getEndpointUrl — returns endpoint from spec
|
|
163
|
+
// ---------------------------------------------------------------------------
|
|
164
|
+
|
|
165
|
+
test('getEndpointUrl returns the endpointUrl from spec', () => {
|
|
166
|
+
const controller = createAgentGatewayConfigController();
|
|
167
|
+
const config = makeGatewayConfig('url-gateway', { endpointUrl: 'https://my-gateway.internal/v2' });
|
|
168
|
+
const url = controller.getEndpointUrl(config);
|
|
169
|
+
|
|
170
|
+
assert.equal(url, 'https://my-gateway.internal/v2', 'must return spec endpointUrl');
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
// ---------------------------------------------------------------------------
|
|
174
|
+
// 10. getFeatureFlags — returns flags with defaults
|
|
175
|
+
// ---------------------------------------------------------------------------
|
|
176
|
+
|
|
177
|
+
test('getFeatureFlags returns feature flags merged with defaults', () => {
|
|
178
|
+
const controller = createAgentGatewayConfigController();
|
|
179
|
+
const config = makeGatewayConfig('flags-gateway', {
|
|
180
|
+
featureFlags: { streaming: false, customFlag: true }
|
|
181
|
+
});
|
|
182
|
+
const flags = controller.getFeatureFlags(config);
|
|
183
|
+
|
|
184
|
+
assert.ok(flags, 'getFeatureFlags must return a value');
|
|
185
|
+
assert.equal(flags.streaming, false, 'streaming flag must be overridden from spec');
|
|
186
|
+
assert.equal(flags.customFlag, true, 'custom flag must be present from spec');
|
|
187
|
+
assert.ok('reconnect' in flags, 'reconnect must have a default');
|
|
188
|
+
assert.ok('healthCheck' in flags, 'healthCheck must have a default');
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
test('getFeatureFlags returns all defaults when no featureFlags in spec', () => {
|
|
192
|
+
const controller = createAgentGatewayConfigController();
|
|
193
|
+
const config = makeGatewayConfig('no-flags-gateway');
|
|
194
|
+
const flags = controller.getFeatureFlags(config);
|
|
195
|
+
|
|
196
|
+
assert.ok(flags, 'getFeatureFlags must return a value');
|
|
197
|
+
assert.ok('streaming' in flags, 'streaming must have a default');
|
|
198
|
+
assert.ok('reconnect' in flags, 'reconnect must have a default');
|
|
199
|
+
assert.ok('healthCheck' in flags, 'healthCheck must have a default');
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
// ---------------------------------------------------------------------------
|
|
203
|
+
// 11. getConnectionPool — returns pool with defaults
|
|
204
|
+
// ---------------------------------------------------------------------------
|
|
205
|
+
|
|
206
|
+
test('getConnectionPool returns connection pool settings merged with defaults', () => {
|
|
207
|
+
const controller = createAgentGatewayConfigController();
|
|
208
|
+
const config = makeGatewayConfig('pool-gateway', { connectionPool: { maxConnections: 50 } });
|
|
209
|
+
const pool = controller.getConnectionPool(config);
|
|
210
|
+
|
|
211
|
+
assert.ok(pool, 'getConnectionPool must return a value');
|
|
212
|
+
assert.equal(pool.maxConnections, 50, 'must use spec maxConnections');
|
|
213
|
+
assert.ok(Number.isFinite(pool.timeoutMs), 'timeoutMs must have a numeric default');
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
test('getConnectionPool returns all defaults when no connectionPool in spec', () => {
|
|
217
|
+
const controller = createAgentGatewayConfigController();
|
|
218
|
+
const config = makeGatewayConfig('no-pool-gateway');
|
|
219
|
+
const pool = controller.getConnectionPool(config);
|
|
220
|
+
|
|
221
|
+
assert.ok(pool, 'getConnectionPool must return a value');
|
|
222
|
+
assert.ok(Number.isFinite(pool.maxConnections), 'maxConnections must have a numeric default');
|
|
223
|
+
assert.ok(Number.isFinite(pool.timeoutMs), 'timeoutMs must have a numeric default');
|
|
224
|
+
assert.ok(pool.maxConnections > 0, 'default maxConnections must be positive');
|
|
225
|
+
assert.ok(pool.timeoutMs >= 0, 'default timeoutMs must be non-negative');
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
// ---------------------------------------------------------------------------
|
|
229
|
+
// 12. getTlsConfigRef — returns ref or null
|
|
230
|
+
// ---------------------------------------------------------------------------
|
|
231
|
+
|
|
232
|
+
test('getTlsConfigRef returns null when no TLS config is set', () => {
|
|
233
|
+
const controller = createAgentGatewayConfigController();
|
|
234
|
+
const config = makeGatewayConfig('no-tls-gateway');
|
|
235
|
+
const ref = controller.getTlsConfigRef(config);
|
|
236
|
+
|
|
237
|
+
assert.equal(ref, null, 'getTlsConfigRef must return null when not set');
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
test('getTlsConfigRef returns the TLS config reference from spec', () => {
|
|
241
|
+
const controller = createAgentGatewayConfigController();
|
|
242
|
+
const config = makeGatewayConfig('tls-gateway', { tlsConfigRef: 'prod-tls-secret' });
|
|
243
|
+
const ref = controller.getTlsConfigRef(config);
|
|
244
|
+
|
|
245
|
+
assert.equal(ref, 'prod-tls-secret', 'getTlsConfigRef must return the spec tlsConfigRef');
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
// ---------------------------------------------------------------------------
|
|
249
|
+
// 13. validate — accumulates multiple errors
|
|
250
|
+
// ---------------------------------------------------------------------------
|
|
251
|
+
|
|
252
|
+
test('validate accumulates all errors when multiple fields are invalid', () => {
|
|
253
|
+
const controller = createAgentGatewayConfigController();
|
|
254
|
+
const config = {
|
|
255
|
+
apiVersion: 'krate.a5c.ai/v1alpha1',
|
|
256
|
+
kind: 'AgentGatewayConfig',
|
|
257
|
+
metadata: { namespace: 'krate-org-default', labels: {}, annotations: {} },
|
|
258
|
+
spec: {},
|
|
259
|
+
status: {}
|
|
260
|
+
};
|
|
261
|
+
const result = controller.validate(config);
|
|
262
|
+
|
|
263
|
+
assert.equal(result.valid, false, 'config with multiple missing fields must fail');
|
|
264
|
+
assert.ok(result.errors.length >= 2, 'must accumulate at least two errors');
|
|
265
|
+
assert.ok(
|
|
266
|
+
result.errors.some((e) => /name/i.test(e)),
|
|
267
|
+
'errors must include a name error'
|
|
268
|
+
);
|
|
269
|
+
assert.ok(
|
|
270
|
+
result.errors.some((e) => /endpointUrl/i.test(e)),
|
|
271
|
+
'errors must include an endpointUrl error'
|
|
272
|
+
);
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
// ---------------------------------------------------------------------------
|
|
276
|
+
// 14. validate / getEndpointUrl / getFeatureFlags — reject null resource
|
|
277
|
+
// ---------------------------------------------------------------------------
|
|
278
|
+
|
|
279
|
+
test('validate rejects null resource with a clear error', () => {
|
|
280
|
+
const controller = createAgentGatewayConfigController();
|
|
281
|
+
const result = controller.validate(null);
|
|
282
|
+
|
|
283
|
+
assert.equal(result.valid, false, 'null resource must fail validation');
|
|
284
|
+
assert.ok(result.errors.length > 0, 'errors array must not be empty');
|
|
285
|
+
assert.ok(
|
|
286
|
+
result.errors.some((e) => /null|undefined/i.test(e)),
|
|
287
|
+
'error must mention null or undefined'
|
|
288
|
+
);
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
test('getEndpointUrl throws on null resource', () => {
|
|
292
|
+
const controller = createAgentGatewayConfigController();
|
|
293
|
+
assert.throws(
|
|
294
|
+
() => controller.getEndpointUrl(null),
|
|
295
|
+
/null|undefined/i,
|
|
296
|
+
'getEndpointUrl must throw on null resource'
|
|
297
|
+
);
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
test('getFeatureFlags throws on null resource', () => {
|
|
301
|
+
const controller = createAgentGatewayConfigController();
|
|
302
|
+
assert.throws(
|
|
303
|
+
() => controller.getFeatureFlags(null),
|
|
304
|
+
/null|undefined/i,
|
|
305
|
+
'getFeatureFlags must throw on null resource'
|
|
306
|
+
);
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
test('getConnectionPool throws on null resource', () => {
|
|
310
|
+
const controller = createAgentGatewayConfigController();
|
|
311
|
+
assert.throws(
|
|
312
|
+
() => controller.getConnectionPool(null),
|
|
313
|
+
/null|undefined/i,
|
|
314
|
+
'getConnectionPool must throw on null resource'
|
|
315
|
+
);
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
test('getTlsConfigRef throws on null resource', () => {
|
|
319
|
+
const controller = createAgentGatewayConfigController();
|
|
320
|
+
assert.throws(
|
|
321
|
+
() => controller.getTlsConfigRef(null),
|
|
322
|
+
/null|undefined/i,
|
|
323
|
+
'getTlsConfigRef must throw on null resource'
|
|
324
|
+
);
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
// ---------------------------------------------------------------------------
|
|
328
|
+
// 15. validateAgentGatewayConfig — standalone export follows existing pattern
|
|
329
|
+
// ---------------------------------------------------------------------------
|
|
330
|
+
|
|
331
|
+
test('validateAgentGatewayConfig standalone export follows existing pattern', () => {
|
|
332
|
+
assert.equal(typeof validateAgentGatewayConfig, 'function', 'validateAgentGatewayConfig must be a named export');
|
|
333
|
+
|
|
334
|
+
const config = makeGatewayConfig('standalone-validate-gateway');
|
|
335
|
+
const result = validateAgentGatewayConfig(config);
|
|
336
|
+
|
|
337
|
+
assert.ok(result, 'validateAgentGatewayConfig must return a result');
|
|
338
|
+
assert.ok('valid' in result, 'result must have a valid property');
|
|
339
|
+
assert.ok(Array.isArray(result.errors), 'result must have an errors array');
|
|
340
|
+
assert.equal(result.valid, true, 'a fully-specified config must pass standalone validation');
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
// ---------------------------------------------------------------------------
|
|
344
|
+
// 16. BOUNDARY — exported with correct role
|
|
345
|
+
// ---------------------------------------------------------------------------
|
|
346
|
+
|
|
347
|
+
test('AGENT_GATEWAY_CONFIG_CONTROLLER_BOUNDARY is exported with correct role', () => {
|
|
348
|
+
assert.ok(AGENT_GATEWAY_CONFIG_CONTROLLER_BOUNDARY, 'BOUNDARY must be exported');
|
|
349
|
+
assert.equal(
|
|
350
|
+
AGENT_GATEWAY_CONFIG_CONTROLLER_BOUNDARY.role,
|
|
351
|
+
'agent-gateway-config-controller',
|
|
352
|
+
'BOUNDARY role must be "agent-gateway-config-controller"'
|
|
353
|
+
);
|
|
354
|
+
assert.ok(
|
|
355
|
+
Array.isArray(AGENT_GATEWAY_CONFIG_CONTROLLER_BOUNDARY.owns),
|
|
356
|
+
'BOUNDARY must declare owned concerns'
|
|
357
|
+
);
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
// ---------------------------------------------------------------------------
|
|
361
|
+
// 17. validate — valid connection pool with explicit timeoutMs=0 is accepted
|
|
362
|
+
// ---------------------------------------------------------------------------
|
|
363
|
+
|
|
364
|
+
test('validate accepts config with timeoutMs=0 (no timeout)', () => {
|
|
365
|
+
const controller = createAgentGatewayConfigController();
|
|
366
|
+
const config = makeGatewayConfig('zero-timeout-gateway', { connectionPool: { maxConnections: 5, timeoutMs: 0 } });
|
|
367
|
+
const result = controller.validate(config);
|
|
368
|
+
|
|
369
|
+
assert.equal(result.valid, true, 'config with timeoutMs=0 must pass validation');
|
|
370
|
+
assert.equal(result.errors.length, 0, 'errors array must be empty');
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
// ---------------------------------------------------------------------------
|
|
374
|
+
// 18. getConnectionPool — both spec values returned when both are set
|
|
375
|
+
// ---------------------------------------------------------------------------
|
|
376
|
+
|
|
377
|
+
test('getConnectionPool returns both spec values when both maxConnections and timeoutMs are set', () => {
|
|
378
|
+
const controller = createAgentGatewayConfigController();
|
|
379
|
+
const config = makeGatewayConfig('full-pool-gateway', {
|
|
380
|
+
connectionPool: { maxConnections: 25, timeoutMs: 5000 }
|
|
381
|
+
});
|
|
382
|
+
const pool = controller.getConnectionPool(config);
|
|
383
|
+
|
|
384
|
+
assert.equal(pool.maxConnections, 25, 'must return spec maxConnections');
|
|
385
|
+
assert.equal(pool.timeoutMs, 5000, 'must return spec timeoutMs');
|
|
386
|
+
});
|