@a5c-ai/krate 5.0.1-staging.69cb593ea → 5.0.1-staging.6be34ee2a

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.
@@ -1,238 +1,187 @@
1
1
  # Krate Requirements Specification v2
2
2
 
3
- > Derived from implementation. Every requirement below corresponds to implemented functionality.
4
-
5
- ## 1. Functional Requirements
6
-
7
- ### FR-IDENTITY: Identity and Access Management
8
-
9
- | ID | Requirement | Source |
10
- |----|-------------|--------|
11
- | FR-IDENTITY-01 | System SHALL support multi-tenant organizations with display name and namespace binding | `resource-model.js:Organization` |
12
- | FR-IDENTITY-02 | System SHALL support user accounts with email, display name, admin flag, and linked identities | `resource-model.js:User` |
13
- | FR-IDENTITY-03 | System SHALL support teams with membership, maintainers, and permission grants | `resource-model.js:Team` |
14
- | FR-IDENTITY-04 | System SHALL support pending invitations with email, role, and team assignment | `resource-model.js:Invite` |
15
- | FR-IDENTITY-05 | System SHALL map between Krate users, sign-in subjects, and external accounts | `resource-model.js:IdentityMapping` |
16
- | FR-IDENTITY-06 | System SHALL support configurable auth providers (GitHub, OIDC/SSO) per org | `resource-model.js:AuthProvider` |
17
- | FR-IDENTITY-07 | System SHALL support agent service accounts for K8s identity binding | `resource-model.js:AgentServiceAccount` |
18
- | FR-IDENTITY-08 | System SHALL project managed RBAC bindings for agent identity | `resource-model.js:AgentRoleBinding` |
19
- | FR-IDENTITY-09 | System SHALL gate secret access through explicit grants with purpose scope | `resource-model.js:AgentSecretGrant` |
20
- | FR-IDENTITY-10 | System SHALL gate ConfigMap access through explicit grants with purpose scope | `resource-model.js:AgentConfigGrant` |
21
-
22
- ### FR-REPOSITORY: Repository Management
23
-
24
- | ID | Requirement | Source |
25
- |----|-------------|--------|
26
- | FR-REPO-01 | System SHALL support repository CRUD with visibility settings | `resource-model.js:Repository` |
27
- | FR-REPO-02 | System SHALL manage user, deploy, and automation SSH keys | `resource-model.js:SSHKey` |
28
- | FR-REPO-03 | System SHALL manage repository collaborator and team permissions | `resource-model.js:RepositoryPermission` |
29
- | FR-REPO-04 | System SHALL enforce branch protection rules | `resource-model.js:BranchProtection` |
30
- | FR-REPO-05 | System SHALL enforce reference deny rules and force-push policies | `resource-model.js:RefPolicy` |
31
- | FR-REPO-06 | System SHALL provide git object recording for repository content | `http-server.js:objects` |
32
- | FR-REPO-07 | System SHALL support search indexing per repository | `http-server.js:search-index` |
33
-
34
- ### FR-POLICY: Policy Management
35
-
36
- | ID | Requirement | Source |
37
- |----|-------------|--------|
38
- | FR-POLICY-01 | System SHALL support organization policy profiles with posture and rollout mode | `resource-model.js:PolicyProfile` |
39
- | FR-POLICY-02 | System SHALL provide curated Kyverno policy templates with parameters | `resource-model.js:PolicyTemplate` |
40
- | FR-POLICY-03 | System SHALL bind templates to orgs/repos with audit/enforce state | `resource-model.js:PolicyBinding` |
41
- | FR-POLICY-04 | System SHALL support auditable exception request workflows with expiry | `resource-model.js:PolicyExceptionRequest` |
42
-
43
- ### FR-AGENT: Agent Orchestration
44
-
45
- | ID | Requirement | Source |
46
- |----|-------------|--------|
47
- | FR-AGENT-01 | System SHALL define reusable agent stacks with model, prompt, tools, MCP, skills | `resource-model.js:AgentStack` |
48
- | FR-AGENT-02 | System SHALL support named child-agent definitions with role/task scoping | `resource-model.js:AgentSubagent` |
49
- | FR-AGENT-03 | System SHALL define tool profiles with filesystem/network/shell policies | `resource-model.js:AgentToolProfile` |
50
- | FR-AGENT-04 | System SHALL manage MCP server endpoints with transport and health checks | `resource-model.js:AgentMcpServer` |
51
- | FR-AGENT-05 | System SHALL support reusable skill bundles with prompt fragments | `resource-model.js:AgentSkill` |
52
- | FR-AGENT-06 | System SHALL route events to agent stacks via trigger rules | `resource-model.js:AgentTriggerRule` |
53
- | FR-AGENT-07 | System SHALL provide reviewed prompt fragments with provenance | `resource-model.js:AgentContextLabel` |
54
- | FR-AGENT-08 | System SHALL create dispatch runs with queue, status, workspace, cost tracking | `resource-model.js:AgentDispatchRun` |
55
- | FR-AGENT-09 | System SHALL track execution attempts with reason and stack snapshot | `resource-model.js:AgentDispatchAttempt` |
56
- | FR-AGENT-10 | System SHALL project Agent Mux sessions with lifecycle state | `resource-model.js:AgentSession` |
57
- | FR-AGENT-11 | System SHALL create immutable context bundles with digest and provenance | `resource-model.js:AgentContextBundle` |
58
- | FR-AGENT-12 | System SHALL store durable agent outputs with kind and retention | `resource-model.js:KrateArtifact` |
59
- | FR-AGENT-13 | System SHALL gate agent actions through human approval workflows | `resource-model.js:AgentApproval` |
60
- | FR-AGENT-14 | System SHALL support adapter definitions with transport/capabilities | `resource-model.js:AgentAdapter` |
61
- | FR-AGENT-15 | System SHALL configure transport bindings with endpoint/protocol/auth | `resource-model.js:AgentTransportBinding` |
62
- | FR-AGENT-16 | System SHALL configure model providers with API base and rate limits | `resource-model.js:AgentProviderConfig` |
63
- | FR-AGENT-17 | System SHALL group issues and repositories into projects with kanban | `resource-model.js:KrateProject` |
64
- | FR-AGENT-18 | System SHALL configure gateway connections with URL and feature flags | `resource-model.js:AgentGatewayConfig` |
65
- | FR-AGENT-19 | System SHALL record session transcripts with message nodes and cost | `resource-model.js:AgentSessionTranscript` |
66
- | FR-AGENT-20 | System SHALL perform permission review before dispatch | `agent-dispatch-controller.js` |
67
- | FR-AGENT-21 | System SHALL provision workspaces during dispatch | `agent-dispatch-controller.js` |
68
- | FR-AGENT-22 | System SHALL perform MCP health checks with 3s timeout | `agent-stack-controller.js` |
69
-
70
- ### FR-MEMORY: Agent Memory
71
-
72
- | ID | Requirement | Source |
73
- |----|-------------|--------|
74
- | FR-MEM-01 | System SHALL point to Git repositories for shared agent memory | `resource-model.js:AgentMemoryRepository` |
75
- | FR-MEM-02 | System SHALL define read policies per repository/team/stack/trigger | `resource-model.js:AgentMemorySource` |
76
- | FR-MEM-03 | System SHALL enforce ontology with required fields and vocabulary | `resource-model.js:AgentMemoryOntology` |
77
- | FR-MEM-04 | System SHALL create immutable memory snapshots at dispatch time | `resource-model.js:AgentMemorySnapshot` |
78
- | FR-MEM-05 | System SHALL execute graph traversal queries with depth/kind filtering | `agent-memory-query.js:queryGraph` |
79
- | FR-MEM-06 | System SHALL execute full-text grep queries with context extraction | `agent-memory-query.js:queryGrep` |
80
- | FR-MEM-07 | System SHALL support combined graph+grep queries | `agent-memory-query.js:queryMemory` |
81
- | FR-MEM-08 | System SHALL track proposed memory mutations with validation | `resource-model.js:AgentMemoryUpdate` |
82
- | FR-MEM-09 | System SHALL import run metadata into memory with redaction | `resource-model.js:AgentRunMemoryImport` |
83
- | FR-MEM-10 | System SHALL bridge memory content to Krate resources | `resource-model.js:AgentMemoryAssociation` |
84
-
85
- ### FR-EXTERNAL: External Backend Integration
86
-
87
- | ID | Requirement | Source |
88
- |----|-------------|--------|
89
- | FR-EXT-01 | System SHALL register external providers with type/endpoint/auth | `resource-model.js:ExternalBackendProvider` |
90
- | FR-EXT-02 | System SHALL bind providers to orgs with credentials | `resource-model.js:ExternalBackendBinding` |
91
- | FR-EXT-03 | System SHALL configure sync intervals and conflict resolution | `resource-model.js:ExternalBackendSyncPolicy` |
92
- | FR-EXT-04 | System SHALL discover provider capabilities automatically | `resource-model.js:ExternalProviderCapabilityManifest` |
93
- | FR-EXT-05 | System SHALL verify inbound webhooks with HMAC-SHA256 | `external/webhook-controller.js` |
94
- | FR-EXT-06 | System SHALL deduplicate webhook deliveries by ID | `external/webhook-controller.js` |
95
- | FR-EXT-07 | System SHALL track sync events with ordering metadata | `resource-model.js:ExternalSyncEvent` |
96
- | FR-EXT-08 | System SHALL maintain current sync phase and error state | `resource-model.js:ExternalSyncState` |
97
- | FR-EXT-09 | System SHALL queue write-back intents with approval state | `resource-model.js:ExternalWriteIntent` |
98
- | FR-EXT-10 | System SHALL detect conflicts with diff and resolution outcome | `resource-model.js:ExternalSyncConflict` |
99
- | FR-EXT-11 | System SHALL maintain stable local-to-external object mappings | `resource-model.js:ExternalObjectLink` |
100
- | FR-EXT-12 | System SHALL provide GitHub adapter (auth, git-forge, issues, CI) | `external/github/` |
101
-
102
- ### FR-CI: Continuous Integration
103
-
104
- | ID | Requirement | Source |
105
- |----|-------------|--------|
106
- | FR-CI-01 | System SHALL track pipeline runs with state and resume point | `resource-model.js:Pipeline` |
107
- | FR-CI-02 | System SHALL define executable job steps with isolation | `resource-model.js:Job` |
108
- | FR-CI-03 | System SHALL manage runner pools with warm/max replicas | `resource-model.js:RunnerPool` |
109
-
110
- ### FR-HOOKS: Webhook Management
111
-
112
- | ID | Requirement | Source |
113
- |----|-------------|--------|
114
- | FR-HOOKS-01 | System SHALL support webhook subscriptions with URL, events, signing | `resource-model.js:WebhookSubscription` |
115
- | FR-HOOKS-02 | System SHALL record durable outbound delivery attempts | `resource-model.js:WebhookDelivery` |
116
-
117
- ### FR-WEB: Web UI
118
-
119
- | ID | Requirement | Source |
120
- |----|-------------|--------|
121
- | FR-WEB-01 | System SHALL support saved triage and dashboard views | `resource-model.js:View` |
122
- | FR-WEB-02 | System SHALL support reusable label/query selectors | `resource-model.js:Selector` |
3
+ > Exhaustive requirements derived from implemented functionality.
4
+ > Every requirement corresponds to verified source code behavior.
123
5
 
124
6
  ---
125
7
 
126
- ## 2. Non-Functional Requirements
127
-
128
- ### NFR-PERF: Performance
129
-
130
- | ID | Requirement | Source |
131
- |----|-------------|--------|
132
- | NFR-PERF-01 | System SHALL cache snapshots with stale-while-revalidate (30s TTL) | `snapshot-cache.js` |
133
- | NFR-PERF-02 | System SHALL support per-org cache entries for independent revalidation | `snapshot-cache.js` |
134
- | NFR-PERF-03 | System SHALL execute kubectl operations asynchronously | `kubernetes-controller-async.js` |
135
- | NFR-PERF-04 | System SHALL batch events with configurable size (50) and interval (1000ms) | `async-controller.js:createEventBatcher` |
136
- | NFR-PERF-05 | System SHALL retry operations with exponential backoff | `async-controller.js:createRetryPolicy` |
137
- | NFR-PERF-06 | System SHALL deliver events via ordered async queue | `async-controller.js:createDeliveryQueue` |
138
- | NFR-PERF-07 | System SHALL checkpoint long-running operations for resumption | `async-controller.js:createCheckpointer` |
139
- | NFR-PERF-08 | System SHALL stream events via SSE with 30s heartbeat keepalive | `http-server.js:sseMatch` |
140
-
141
- ### NFR-SEC: Security
142
-
143
- | ID | Requirement | Source |
144
- |----|-------------|--------|
145
- | NFR-SEC-01 | System SHALL sign session cookies with HMAC-SHA256 | `auth.js:createSessionCookie` |
146
- | NFR-SEC-02 | System SHALL use timing-safe comparison for signatures | `auth.js:timingSafeEqual` |
147
- | NFR-SEC-03 | System SHALL require auth on all mutating API routes | `http-server.js` |
148
- | NFR-SEC-04 | System SHALL reject unsigned cookies when secret is configured | `auth.js:parseSessionCookie` |
149
- | NFR-SEC-05 | System SHALL verify webhook signatures with HMAC-SHA256 | `external/webhook-controller.js` |
150
- | NFR-SEC-06 | System SHALL set HttpOnly and SameSite=Lax on session cookies | `auth.js:createSessionCookie` |
151
- | NFR-SEC-07 | System SHALL enforce org namespace isolation for all resources | `http-server.js:scopeResource` |
152
- | NFR-SEC-08 | System SHALL use RBAC ClusterRole for CRD access | `kubernetes-controller.js` |
153
-
154
- ### NFR-A11Y: Accessibility
155
-
156
- | ID | Requirement | Source |
157
- |----|-------------|--------|
158
- | NFR-A11Y-01 | Web console SHALL provide aria-label attributes on interactive elements | `packages/krate/web/` |
159
- | NFR-A11Y-02 | Web console SHALL support keyboard navigation | `keyboard-shortcuts.jsx` |
160
- | NFR-A11Y-03 | Web console SHALL provide command palette (Cmd+K) for quick access | `command-palette.jsx` |
161
-
162
- ### NFR-RESPONSIVE: Responsiveness
163
-
164
- | ID | Requirement | Source |
165
- |----|-------------|--------|
166
- | NFR-RESP-01 | Web console SHALL adapt layout for mobile viewports | `packages/krate/web/` CSS |
167
- | NFR-RESP-02 | Web console SHALL provide dark/light theme with system preference | `theme-runtime.jsx` |
8
+ ## 1. Functional Requirements — Identity and Access
9
+
10
+ | ID | Priority | Description | Acceptance Criteria | Implementation | Test Coverage | Status |
11
+ |----|----------|-------------|--------------------:|----------------|---------------|--------|
12
+ | REQ-FUNC-IAM-001 | MUST | Multi-tenant organizations with display name and namespace binding | Organization resource created with displayName and namespaceName; OrgNamespaceBinding created; tenant namespace created in K8s | `kubernetes-controller.js:createOrganization()` | `tests/kubernetes-controller.test.js` | Implemented |
13
+ | REQ-FUNC-IAM-002 | MUST | User accounts with email, display name, admin flag | User resource created with required spec fields; admin derived from group membership | `auth.js:mapLoginProfileToKrateIdentity()` | `tests/auth.test.js` | Implemented |
14
+ | REQ-FUNC-IAM-003 | MUST | Teams with membership, maintainers, and permission grants | Team resource with members[], maintainers[], repositoryGrants[]; memberCount in status | `auth.js:createTeamResource()` | `tests/auth.test.js` | Implemented |
15
+ | REQ-FUNC-IAM-004 | MUST | Pending invitations with email, role, team, and expiry | Invite resource with expiresAt computed from expiresInDays; phase=Pending | `auth.js:createInviteResource()` | `tests/auth.test.js` | Implemented |
16
+ | REQ-FUNC-IAM-005 | MUST | Identity mapping between Krate users and external subjects | IdentityMapping with workspaceIdentity and repositoryIdentity sub-objects | `auth.js:mapLoginProfileToKrateIdentity()` | `tests/auth.test.js` | Implemented |
17
+ | REQ-FUNC-IAM-006 | MUST | Configurable auth providers (GitHub OAuth, OIDC/SSO, Delegated) | AuthProvider resource per provider; environment-driven configuration | `auth.js:createAuthProviderConfig()` | `tests/auth.test.js` | Implemented |
18
+ | REQ-FUNC-IAM-007 | MUST | Agent service accounts for K8s identity binding | AgentServiceAccount with namespace and serviceAccountName fields | `resource-model.js` | `tests/resource-model.test.js` | Implemented |
19
+ | REQ-FUNC-IAM-008 | MUST | Managed RBAC projection for agent identity | AgentRoleBinding with subject, roleRef, scope fields | `agent-permission-review.js` | `tests/agent-permission-review.test.js` | Implemented |
20
+ | REQ-FUNC-IAM-009 | MUST | Explicit secret access grants with purpose scope | AgentSecretGrant with subject, secretRef, purpose; validated by permission reviewer | `agent-secret-config-grant-controller.js` | `tests/agent-secret-config-grant.test.js` | Implemented |
21
+ | REQ-FUNC-IAM-010 | MUST | Explicit ConfigMap access grants with purpose scope | AgentConfigGrant with subject, configMapRef, purpose; validated by permission reviewer | `agent-secret-config-grant-controller.js` | `tests/agent-secret-config-grant.test.js` | Implemented |
22
+ | REQ-FUNC-IAM-011 | MUST | Admin detection from group membership | Groups `krate:platform-engineers` or `krate:repo-admins` set admin=true | `auth.js:normalizeProviderProfile()` line 124 | `tests/auth.test.js` | Implemented |
23
+ | REQ-FUNC-IAM-012 | MUST | Bootstrap admin via KRATE_ADMIN_USERNAME | Username match against profile sets isBootstrapAdmin | `auth.js:registerLoginProfile()` line 143 | `tests/auth.test.js` | Implemented |
168
24
 
169
25
  ---
170
26
 
171
- ## 3. Integration Requirements
27
+ ## 2. Functional Requirements — Authentication
28
+
29
+ | ID | Priority | Description | Acceptance Criteria | Implementation | Test Coverage | Status |
30
+ |----|----------|-------------|--------------------:|----------------|---------------|--------|
31
+ | REQ-FUNC-AUTH-001 | MUST | GitHub OAuth sign-in flow | Authorization URL built with client_id, redirect_uri, scope, state; code exchanged for access_token; profile fetched from /user | `auth.js:buildAuthorizationRedirect(), exchangeOAuthCodeForProfile()` | `tests/auth.test.js` | Implemented |
32
+ | REQ-FUNC-AUTH-002 | MUST | OIDC/SSO sign-in flow | Same OAuth flow with configurable issuer/token/userinfo endpoints; scopes include groups | `auth.js:exchangeOAuthCodeForProfile()` | `tests/auth.test.js` | Implemented |
33
+ | REQ-FUNC-AUTH-003 | MUST | Delegated identity via proxy headers | x-forwarded-user, x-forwarded-groups, x-forwarded-email parsed; local dev fallback | `auth.js:profileFromDelegatedHeaders()` | `tests/auth.test.js` | Implemented |
34
+ | REQ-FUNC-AUTH-004 | MUST | HMAC-SHA256 signed session cookies | Payload base64url encoded; signature = HMAC-SHA256(payload, secret).base64url | `auth.js:createSessionCookie()` | `tests/auth.test.js` | Implemented |
35
+ | REQ-FUNC-AUTH-005 | MUST | Timing-safe signature verification | `timingSafeEqual(expected, received)` from node:crypto | `auth.js:parseSessionCookie()` line 189 | `tests/auth.test.js` | Implemented |
36
+ | REQ-FUNC-AUTH-006 | MUST | Reject unsigned cookies when secret configured | If dotIndex === -1 and secret is set: return null | `auth.js:parseSessionCookie()` line 178 | `tests/auth.test.js` | Implemented |
37
+ | REQ-FUNC-AUTH-007 | MUST | Reject signed cookies when no secret | If dotIndex !== -1 and no secret: return null | `auth.js:parseSessionCookie()` line 172 | `tests/auth.test.js` | Implemented |
38
+ | REQ-FUNC-AUTH-008 | MUST | HttpOnly and SameSite=Lax cookie attributes | Cookie string ends with `; Path=/; HttpOnly; SameSite=Lax` | `auth.js:createSessionCookie()` line 162 | `tests/auth.test.js` | Implemented |
39
+ | REQ-FUNC-AUTH-009 | SHOULD | Local development auto-login | Active when NODE_ENV !== 'production'; configurable user/groups | `auth.js:localDelegatedDevelopmentProfile()` | `tests/auth.test.js` | Implemented |
40
+ | REQ-FUNC-AUTH-010 | MUST | User+IdentityMapping registration on first login | registerLoginProfile creates/updates User and IdentityMapping resources via applyResource | `auth.js:registerLoginProfile()` | `tests/auth.test.js` | Implemented |
172
41
 
173
- ### INT-K8S: Kubernetes
42
+ ---
43
+
44
+ ## 3. Functional Requirements — Repository Management
45
+
46
+ | ID | Priority | Description | Acceptance Criteria | Implementation | Test Coverage | Status |
47
+ |----|----------|-------------|--------------------:|----------------|---------------|--------|
48
+ | REQ-FUNC-REPO-001 | MUST | Repository CRUD with visibility | Repository created with organizationRef, visibility (private/internal/public); delete removes CRD | `api-controller.js:createRepository()` | `tests/api-controller.test.js` | Implemented |
49
+ | REQ-FUNC-REPO-002 | MUST | SSH key management (user, deploy, automation scopes) | SSHKey with scope field; fingerprint computed via sha256 hash | `kubernetes-controller.js:identityAccessReconciliationPlan()` | `tests/kubernetes-controller.test.js` | Implemented |
50
+ | REQ-FUNC-REPO-003 | MUST | Repository permission management | RepositoryPermission with subject, permission (read/write/admin), revoked flag | `kubernetes-controller.js:identityAccessReconciliationPlan()` | `tests/kubernetes-controller.test.js` | Implemented |
51
+ | REQ-FUNC-REPO-004 | MUST | Branch protection rules | BranchProtection with refs pattern; PR requirement enforcement | `resource-model.js` | `tests/resource-model.test.js` | Implemented |
52
+ | REQ-FUNC-REPO-005 | MUST | Reference deny rules and force-push policy | RefPolicy resource with organizationRef | `resource-model.js` | `tests/resource-model.test.js` | Implemented |
53
+ | REQ-FUNC-REPO-006 | MUST | Git object recording | POST /api/orgs/:org/repositories/:repo/objects stores object reference | `http-server.js` line 60-63 | `tests/http-server.test.js` | Implemented |
54
+ | REQ-FUNC-REPO-007 | MUST | Search index enqueuing | POST returns 202 Accepted; search indexing queued asynchronously | `http-server.js` line 66-70 | `tests/http-server.test.js` | Implemented |
55
+
56
+ ---
57
+
58
+ ## 4. Functional Requirements — Agent Orchestration
59
+
60
+ | ID | Priority | Description | Acceptance Criteria | Implementation | Test Coverage | Status |
61
+ |----|----------|-------------|--------------------:|----------------|---------------|--------|
62
+ | REQ-FUNC-AGENT-001 | MUST | Reusable agent stacks with full config | AgentStack with baseAgent, adapter, runtimeIdentity, toolPolicy, mcpServerRefs, skillRefs, subagentRefs, contextLabelRefs, approvalMode | `agent-stack-controller.js` | `tests/agent-stack-controller.test.js` | Implemented |
63
+ | REQ-FUNC-AGENT-002 | MUST | Stack readiness reconciliation with 10 conditions | reconcileStack() resolves all refs, runs permission review, computes Ready condition | `agent-stack-controller.js:reconcileStack()` | `tests/agent-stack-controller.test.js` | Implemented |
64
+ | REQ-FUNC-AGENT-003 | MUST | MCP health check with 3s timeout | HTTP GET to endpoint with AbortController timeout; returns healthy/unhealthy + latencyMs | `agent-stack-controller.js:checkMcpHealth()` | `tests/agent-stack-controller.test.js` | Implemented |
65
+ | REQ-FUNC-AGENT-004 | MUST | Manual dispatch with permission gating | createManualDispatch: find stack → permission review → memory snapshot → workspace → context → launch | `agent-dispatch-controller.js` | `tests/agent-dispatch-controller.test.js` | Implemented |
66
+ | REQ-FUNC-AGENT-005 | MUST | Permission review with cross-org denial | Cross-org check: agent org vs repository org; denied if mismatch | `agent-permission-review.js` line 44-52 | `tests/agent-permission-review.test.js` | Implemented |
67
+ | REQ-FUNC-AGENT-006 | MUST | Untrusted fork detection | Refs matching `/^refs\/pull\/\d+\//` flagged as fork; privileged grants restricted | `agent-permission-review.js` line 64 | `tests/agent-permission-review.test.js` | Implemented |
68
+ | REQ-FUNC-AGENT-007 | MUST | Approval mode enforcement (yolo/prompt/deny) | deny: immediate block; prompt: requires-approval; yolo: allowed | `agent-permission-review.js` lines 34-40 | `tests/agent-permission-review.test.js` | Implemented |
69
+ | REQ-FUNC-AGENT-008 | MUST | Workspace provisioning with PVC | createWorkspace generates KrateWorkspace + PVC manifest with storage class, capacity, access modes | `agent-workspace-controller.js:createWorkspace()` | `tests/agent-workspace-controller.test.js` | Implemented |
70
+ | REQ-FUNC-AGENT-009 | MUST | Workspace reuse by repo+branch+phase | findReusableWorkspace matches org+repo+branch+Ready phase | `agent-workspace-controller.js:findReusableWorkspace()` | `tests/agent-workspace-controller.test.js` | Implemented |
71
+ | REQ-FUNC-AGENT-010 | MUST | Codespace lifecycle (launch/stop/status) | Pod spec with code-server image, PVC mount, Service with ClusterIP | `agent-workspace-controller.js:launchCodespace()` | `tests/agent-workspace-controller.test.js` | Implemented |
72
+ | REQ-FUNC-AGENT-011 | MUST | Event-to-stack routing via trigger rules | evaluateEvent matches event type against rule sources; dedup check; dispatch creation | `agent-trigger-controller.js:processEvent()` | `tests/agent-trigger-controller.test.js` | Implemented |
73
+ | REQ-FUNC-AGENT-012 | MUST | Cron expression validation (5-field) | validateCronExpression checks 5 fields, valid chars [0-9*/,-] | `agent-trigger-controller.js:validateCronExpression()` | `tests/agent-trigger-controller.test.js` | Implemented |
74
+ | REQ-FUNC-AGENT-013 | MUST | Next cron run calculation | calculateNextRun iterates minute-by-minute up to 527,040 iterations (1 year) | `agent-trigger-controller.js:calculateNextRun()` | `tests/agent-trigger-controller.test.js` | Implemented |
75
+ | REQ-FUNC-AGENT-014 | MUST | Human approval gates for agent actions | createApprovalRequest with 5 valid actions; recordDecision approve/deny; dedup check | `agent-approval-controller.js` | `tests/agent-approval-controller.test.js` | Implemented |
76
+ | REQ-FUNC-AGENT-015 | MUST | Approval enforcement gate | enforceApproval returns allowed/denied/pending based on phase | `agent-approval-controller.js:enforceApproval()` | `tests/agent-approval-controller.test.js` | Implemented |
77
+ | REQ-FUNC-AGENT-016 | MUST | Work item linking (issues/PRs to sessions/workspaces) | WorkItemSessionLink and WorkItemWorkspaceLink resources created | `agent-workspace-controller.js:linkWorkItem(), linkWorkItemToSession()` | `tests/agent-workspace-controller.test.js` | Implemented |
78
+ | REQ-FUNC-AGENT-017 | MUST | Workspace associations | addAssociation/removeAssociation with valid kinds: AgentDispatchRun, User, AgentSession | `agent-workspace-controller.js:addAssociation()` | `tests/agent-workspace-controller.test.js` | Implemented |
79
+ | REQ-FUNC-AGENT-018 | MUST | Workspace run history | getWorkspaceRuns partitions into active (Running/Queued/Pending/Dispatched) and history | `agent-workspace-controller.js:getWorkspaceRuns()` | `tests/agent-workspace-controller.test.js` | Implemented |
80
+
81
+ ---
174
82
 
175
- | ID | Requirement | Source |
176
- |----|-------------|--------|
177
- | INT-K8S-01 | System SHALL store CONFIG resources as Kubernetes CRDs | `kubernetes-controller.js` |
178
- | INT-K8S-02 | System SHALL use kubectl for resource operations | `kubernetes-controller.js:spawn` |
179
- | INT-K8S-03 | System SHALL define 75 CRDs under `krate.a5c.ai/v1alpha1` | `kubernetes-controller.js:KRATE_RESOURCES` |
180
- | INT-K8S-04 | System SHALL scope resources to org namespaces (`krate-org-{org}`) | `org-scoping.js:orgNamespaceName` |
181
- | INT-K8S-05 | System SHALL manage PersistentVolumeClaims for workspaces | `agent-workspace-controller.js` |
182
- | INT-K8S-06 | System SHALL use `x-kubernetes-preserve-unknown-fields` for extensibility | CRD definitions |
83
+ ## 5. Functional Requirements Memory System
84
+
85
+ | ID | Priority | Description | Acceptance Criteria | Implementation | Test Coverage | Status |
86
+ |----|----------|-------------|--------------------:|----------------|---------------|--------|
87
+ | REQ-FUNC-MEM-001 | MUST | Graph query with nodeKind filtering and depth | queryGraph: records filtered by kinds[], scored by id/attribute match, edges followed to depth | `agent-memory-query.js:queryGraph()` | `tests/agent-memory-query.test.js` | Implemented |
88
+ | REQ-FUNC-MEM-002 | MUST | Full-text grep with context extraction | queryGrep: line-by-line case-insensitive search; context lines above/below; highlighted output | `agent-memory-query.js:queryGrep()` | `tests/agent-memory-query.test.js` | Implemented |
89
+ | REQ-FUNC-MEM-003 | MUST | Combined graph+grep query | queryMemory: mode selects graph-only, grep-only, or both; merged stats | `agent-memory-query.js:queryMemory()` | `tests/agent-memory-query.test.js` | Implemented |
90
+ | REQ-FUNC-MEM-004 | MUST | Query validation (non-empty string required) | Throws Error if query is null, undefined, or empty string | `agent-memory-query.js` lines 42-45 | `tests/agent-memory-query.test.js` | Implemented |
91
+ | REQ-FUNC-MEM-005 | MUST | Mode validation | Throws Error if mode not in ['graph-only', 'grep-only', 'graph-and-grep'] | `agent-memory-query.js` line 168 | `tests/agent-memory-query.test.js` | Implemented |
92
+ | REQ-FUNC-MEM-006 | MUST | Grep path filtering with glob patterns | Glob match: * matches any sequence; documents filtered before search | `agent-memory-query.js:globMatch()` | `tests/agent-memory-query.test.js` | Implemented |
93
+ | REQ-FUNC-MEM-007 | MUST | Grep max matches limit | Default 25; stops searching once limit reached | `agent-memory-query.js:queryGrep()` line 106 | `tests/agent-memory-query.test.js` | Implemented |
94
+ | REQ-FUNC-MEM-008 | MUST | Graph adjacency from both record edges and flat edges | buildAdjacency merges per-record edges[] with flat edges parameter | `agent-memory-query.js:buildAdjacency()` | `tests/agent-memory-query.test.js` | Implemented |
95
+ | REQ-FUNC-MEM-009 | MUST | BFS edge traversal with cycle prevention | visited Set prevents infinite loops; frontier-based BFS up to maxDepth | `agent-memory-query.js:followEdges()` | `tests/agent-memory-query.test.js` | Implemented |
96
+ | REQ-FUNC-MEM-010 | MUST | Memory import from babysitter runs | parseJournalForImport extracts importable data; validateMemoryImport checks structure | `agent-memory-import.js` | `tests/agent-memory-import.test.js` | Implemented |
183
97
 
184
- ### INT-GITEA: Gitea Integration
98
+ ---
99
+
100
+ ## 6. Functional Requirements — External Backend Integration
101
+
102
+ | ID | Priority | Description | Acceptance Criteria | Implementation | Test Coverage | Status |
103
+ |----|----------|-------------|--------------------:|----------------|---------------|--------|
104
+ | REQ-FUNC-EXT-001 | MUST | HMAC-SHA256 webhook signature verification | sha256= prefix; createHmac + timingSafeEqual; reject on mismatch | `external/webhook-controller.js:verifyHmacSignature()` | `tests/external/webhook-controller.test.js` | Implemented |
105
+ | REQ-FUNC-EXT-002 | MUST | Delivery deduplication by ID | isDuplicate(deliveryId) checks Map; processDelivery returns duplicate=true if exists | `external/webhook-controller.js:isDuplicate()` | `tests/external/webhook-controller.test.js` | Implemented |
106
+ | REQ-FUNC-EXT-003 | MUST | Event normalization from raw provider format | normalizeEvent produces canonical { eventType, action, nativeId, providerRef, resourceKind, data, timestamps } | `external/sync-controller.js:normalizeEvent()` | `tests/external/sync-controller.test.js` | Implemented |
107
+ | REQ-FUNC-EXT-004 | MUST | Resource upsert with external envelope | upsertResource stores nativeId, url, etag, providerRef, firstSyncedAt, lastSyncedAt | `external/sync-controller.js:upsertResource()` | `tests/external/sync-controller.test.js` | Implemented |
108
+ | REQ-FUNC-EXT-005 | MUST | High-watermark tracking per binding | updateWatermark only advances forward; getWatermark returns current | `external/sync-controller.js:updateWatermark()` | `tests/external/sync-controller.test.js` | Implemented |
109
+ | REQ-FUNC-EXT-006 | MUST | Ownership mode enforcement | bidirectional=allow all; external-owned=block krate writes; krate-owned=block external writes | `external/sync-controller.js:applyOwnershipMode()` | `tests/external/sync-controller.test.js` | Implemented |
110
+ | REQ-FUNC-EXT-007 | MUST | Tombstone creation for deleted externals | createTombstone stores nativeId, providerRef, localRef, deletedAt, tombstoned=true | `external/sync-controller.js:createTombstone()` | `tests/external/sync-controller.test.js` | Implemented |
111
+ | REQ-FUNC-EXT-008 | MUST | Field-level conflict detection | detectConflict compares localValue vs externalValue; creates ExternalSyncConflict if different | `external/conflict-controller.js:detectConflict()` | `tests/external/conflict-controller.test.js` | Implemented |
112
+ | REQ-FUNC-EXT-009 | MUST | Conflict resolution with 4 strategies | prefer-external, prefer-krate, manual, ignore; resolveConflict sets phase=Resolved | `external/conflict-controller.js:resolveConflict()` | `tests/external/conflict-controller.test.js` | Implemented |
113
+ | REQ-FUNC-EXT-010 | MUST | Write intent lifecycle with approval | createWriteIntent → PendingApproval → ReadyToSend → Sending → Succeeded/Failed | `external/write-controller.js` | `tests/external/write-controller.test.js` | Implemented |
114
+ | REQ-FUNC-EXT-011 | MUST | Write intent idempotency key | Deterministic djb2 hash of (interfaceKey, operation, resourceRef, payload) | `external/write-controller.js:getIdempotencyKey()` | `tests/external/write-controller.test.js` | Implemented |
115
+ | REQ-FUNC-EXT-012 | MUST | GitHub adapter (auth, git-forge, issues, CI) | Separate modules: auth.js, git-forge.js, issue-tracking.js, cicd.js, index.js | `external/github/` | `tests/external/github/` | Implemented |
116
+
117
+ ---
185
118
 
186
- | ID | Requirement | Source |
187
- |----|-------------|--------|
188
- | INT-GITEA-01 | System SHALL use Gitea for repository hosting | `gitea-service.js` |
189
- | INT-GITEA-02 | System SHALL access Gitea tree/blob/branch APIs | `gitea-backend.js` |
190
- | INT-GITEA-03 | System SHALL sync SSH keys with Gitea repositories | `gitea-service.js` |
119
+ ## 7. Non-Functional Requirements Performance
191
120
 
192
- ### INT-ATLAS: Atlas Graph
121
+ | ID | Priority | Description | Acceptance Criteria | Implementation | Status |
122
+ |----|----------|-------------|--------------------:|----------------|--------|
123
+ | NFR-PERF-001 | MUST | Stale-while-revalidate cache with 30s TTL | Return stale data immediately; background refresh; configurable via KRATE_SNAPSHOT_CACHE_TTL_MS | `snapshot-cache.js:staleWhileRevalidate()` | Implemented |
124
+ | NFR-PERF-002 | MUST | Per-org independent cache entries | Map-based; each org revalidates independently | `snapshot-cache.js:orgCacheMap` | Implemented |
125
+ | NFR-PERF-003 | MUST | Event batching with configurable flush | maxBatchSize=50, flushIntervalMs=1000; fire-and-forget on size limit | `async-controller.js:createEventBatcher()` | Implemented |
126
+ | NFR-PERF-004 | MUST | Exponential backoff retry with jitter | baseDelay * 2^attempt, capped at maxDelay; full-jitter option | `async-controller.js:createRetryPolicy()` | Implemented |
127
+ | NFR-PERF-005 | MUST | Concurrent delivery queue | configurable concurrency (default 5); ordered processing | `async-controller.js:createDeliveryQueue()` | Implemented |
128
+ | NFR-PERF-006 | MUST | SSE heartbeat every 30 seconds | setInterval(30000) writes heartbeat JSON | `http-server.js` line 302 | Implemented |
129
+ | NFR-PERF-007 | MUST | kubectl timeout protection | spawnSync with configurable timeout (default 3s) | `kubernetes-controller.js:runKubectl()` | Implemented |
130
+ | NFR-PERF-008 | MUST | 32MB kubectl output buffer | maxBuffer: KRATE_KUBECTL_MAX_BUFFER_BYTES | `kubernetes-controller.js:runKubectl()` | Implemented |
193
131
 
194
- | ID | Requirement | Source |
195
- |----|-------------|--------|
196
- | INT-ATLAS-01 | SDK SHALL provide Atlas graph search client | `sdk/src/atlas-graph-client.js` |
197
- | INT-ATLAS-02 | SDK SHALL expose stack layers and composition facets | `sdk/src/atlas-graph-client.js:STACK_LAYERS, COMPOSITION_FACETS` |
198
- | INT-ATLAS-03 | Web console SHALL provide Atlas search API route | `web/app/api/atlas/search/route.js` |
132
+ ---
199
133
 
200
- ### INT-GITHUB: GitHub Integration
134
+ ## 8. Non-Functional Requirements — Security
201
135
 
202
- | ID | Requirement | Source |
203
- |----|-------------|--------|
204
- | INT-GH-01 | System SHALL support GitHub as OAuth sign-in provider | `auth.js:github` |
205
- | INT-GH-02 | System SHALL ingest GitHub webhooks with signature verification | `external/webhook-controller.js` |
206
- | INT-GH-03 | System SHALL provide GitHub adapter for git-forge operations | `external/github/git-forge.js` |
207
- | INT-GH-04 | System SHALL provide GitHub adapter for issue tracking | `external/github/issue-tracking.js` |
208
- | INT-GH-05 | System SHALL provide GitHub adapter for CI/CD operations | `external/github/cicd.js` |
209
- | INT-GH-06 | System SHALL handle GitHub App authentication | `external/github/auth.js` |
136
+ | ID | Priority | Description | Acceptance Criteria | Implementation | Status |
137
+ |----|----------|-------------|--------------------:|----------------|--------|
138
+ | NFR-SEC-001 | MUST | HMAC-SHA256 session cookie signing | createHmac('sha256', secret).update(payload).digest('base64url') | `auth.js:createSessionCookie()` | Implemented |
139
+ | NFR-SEC-002 | MUST | Timing-safe signature comparison | `timingSafeEqual` from node:crypto; length check before compare | `auth.js:parseSessionCookie()` line 189 | Implemented |
140
+ | NFR-SEC-003 | MUST | Auth on all mutating API routes | POST/DELETE routes check session; read routes generally unprotected | `http-server.js` | Implemented |
141
+ | NFR-SEC-004 | MUST | Cross-org namespace isolation | applyResource/deleteResourceForOrg verify namespace matches org | `api-controller.js` lines 85-100 | Implemented |
142
+ | NFR-SEC-005 | MUST | HMAC-SHA256 webhook signature verification | External webhook controller uses timing-safe comparison | `external/webhook-controller.js` | Implemented |
143
+ | NFR-SEC-006 | MUST | Delivery deduplication prevents replay | Map-based check before processing; duplicate returns early | `external/webhook-controller.js:isDuplicate()` | Implemented |
144
+ | NFR-SEC-007 | MUST | No secrets in permission review output | permissionReviewer mustNotOwn: 'secret values' | `agent-permission-review.js` boundary | Implemented |
145
+ | NFR-SEC-008 | MUST | Fork-restricted privileged grants | Untrusted fork detection blocks AgentServiceAccount/AgentSecretGrant auto-approval | `agent-permission-review.js` line 66-73 | Implemented |
210
146
 
211
147
  ---
212
148
 
213
- ## 4. Deployment Requirements
149
+ ## 9. Non-Functional Requirements — Reliability
150
+
151
+ | ID | Priority | Description | Acceptance Criteria | Implementation | Status |
152
+ |----|----------|-------------|--------------------:|----------------|--------|
153
+ | NFR-REL-001 | MUST | Audit failures must not crash operations | try/catch around emitAuditEvent; swallowed silently | `api-controller.js:emitAuditEvent()` | Implemented |
154
+ | NFR-REL-002 | MUST | Background revalidation errors reset flag | catch block clears revalidating=false for retry | `snapshot-cache.js:staleWhileRevalidate()` | Implemented |
155
+ | NFR-REL-003 | MUST | Fire-and-forget persistence in external controllers | `Promise.resolve(persistFn(resource)).catch(() => {})` | All external controllers | Implemented |
156
+ | NFR-REL-004 | MUST | Delivery queue error isolation | processItem catches; retries per policy; swallows after max | `async-controller.js:createDeliveryQueue()` | Implemented |
157
+ | NFR-REL-005 | MUST | Graceful degraded snapshot on kubectl failure | Returns partial snapshot with errors[] array; resources empty | `kubernetes-controller.js:getControllerSnapshot()` | Implemented |
158
+
159
+ ---
214
160
 
215
- | ID | Requirement | Source |
216
- |----|-------------|--------|
217
- | DEP-HELM-01 | System SHALL deploy via Helm chart | Helm chart directory |
218
- | DEP-HELM-02 | Helm chart SHALL manage CRD lifecycle | Chart templates |
219
- | DEP-HELM-03 | Helm chart SHALL create org namespace on install | Chart templates |
220
- | DEP-DOCKER-01 | System SHALL use multi-stage Docker builds | Dockerfile |
221
- | DEP-DOCKER-02 | Deployment SHALL run multi-container pods (api, controllers, web, webhook-worker) | Helm values |
222
- | DEP-AKS-01 | System SHALL deploy to Azure Kubernetes Service | Deployment docs |
223
- | DEP-AKS-02 | System SHALL use Azure Container Registry for images | Deployment docs |
224
- | DEP-CERT-01 | System SHALL use cert-manager for TLS certificates | Ingress annotations |
225
- | DEP-INGRESS-01 | System SHALL use nginx ingress controller for HTTP routing | Ingress resource |
161
+ ## 10. Integration Requirements
162
+
163
+ | ID | Priority | Description | Acceptance Criteria | Implementation | Status |
164
+ |----|----------|-------------|--------------------:|----------------|--------|
165
+ | INT-K8S-001 | MUST | Store CONFIG resources as CRDs | kubectl apply/get/delete with krate.a5c.ai group | `kubernetes-controller.js` | Implemented |
166
+ | INT-K8S-002 | MUST | Use kubectl for all K8s operations | spawnSync/spawn with configurable binary path | `kubernetes-controller.js:runKubectl()` | Implemented |
167
+ | INT-K8S-003 | MUST | In-cluster authentication support | Auto-detect SA token + CA cert; inject --server/--token/--certificate-authority | `kubernetes-controller.js:inClusterKubectlConfig()` | Implemented |
168
+ | INT-K8S-004 | MUST | Namespace auto-creation | ensureNamespace before apply; kubectl create namespace if not exists | `kubernetes-controller.js:ensureNamespace()` | Implemented |
169
+ | INT-K8S-005 | MUST | SubjectAccessReview for permission discovery | `kubectl auth can-i <verb> <resource>` for each CRD | `kubernetes-controller.js:canI()` | Implemented |
170
+ | INT-GITEA-001 | MUST | Repository hosting via Gitea | createGiteaService with baseUrl and token | `gitea-service.js` | Implemented |
171
+ | INT-ATLAS-001 | SHOULD | Atlas graph search for stack builder | fetchAtlasRecordsByKinds queries /api/v1/kinds/{kind}; searchAtlasGraph queries /api/v1/search | `sdk/src/atlas-graph-client.js` | Implemented |
172
+ | INT-GH-001 | MUST | GitHub webhook normalization | normalizeWebhookEvent handles workflow_run, PR, comment, label, push | `http-server.js:normalizeWebhookEvent()` | Implemented |
173
+ | INT-KYVERNO-001 | SHOULD | Kyverno policy engine integration | CRD discovery; controller health check; policy report aggregation | `kubernetes-controller.js:discoverKyverno()` | Implemented |
174
+ | INT-KUBEVELA-001 | SHOULD | KubeVela application delivery | Application, Revision, Component, Trait, Scope discovery | `kubernetes-controller.js:KRATE_RESOURCES` | Implemented |
226
175
 
227
176
  ---
228
177
 
229
- ## 5. Testing Requirements
178
+ ## 11. Testing Requirements
230
179
 
231
- | ID | Requirement | Coverage | Source |
232
- |----|-------------|----------|--------|
233
- | TEST-CORE-01 | Core package SHALL have 1259 unit+integration tests | `node:test` | `packages/krate/core/package.json` |
234
- | TEST-SDK-01 | SDK package SHALL have 73 export and integration tests | `node:test` | `packages/krate/sdk/tests/` |
235
- | TEST-CLI-01 | CLI package SHALL have 51 command and MCP protocol tests | `node:test` | `packages/krate/cli/tests/` |
236
- | TEST-E2E-01 | Core SHALL have 3 end-to-end validation tests | `npm run e2e` | `packages/krate/core/package.json` |
237
- | TEST-SMOKE-01 | Core SHALL have 21 MVP smoke assertions | `npm run smoke` | `packages/krate/core/package.json` |
238
- | TEST-WEB-01 | Web console SHALL have build validation tests | `npm run build` | `packages/krate/web/package.json` |
180
+ | ID | Description | Framework | Count | Source |
181
+ |----|-------------|-----------|-------|--------|
182
+ | TEST-CORE-001 | Core package unit+integration tests | node:test | 1259 | `packages/krate/core/package.json` |
183
+ | TEST-SDK-001 | SDK export and integration tests | node:test | 73 | `packages/krate/sdk/tests/` |
184
+ | TEST-CLI-001 | CLI command and MCP protocol tests | node:test | 51 | `packages/krate/cli/tests/` |
185
+ | TEST-E2E-001 | End-to-end package validation | npm run e2e | 3 | `packages/krate/core/package.json` |
186
+ | TEST-SMOKE-001 | MVP smoke assertions | npm run smoke | 21 | `packages/krate/core/package.json` |
187
+ | TEST-WEB-001 | Web console build validation | npm run build | 1 | `packages/krate/web/package.json` |