Repository navigation
feat(adlc): add Agent Declarative Lifecycle Configuration spec - #452
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
Amber reviewStatus: Complete |
HyperShell environment destroyedThis ephemeral OpenShift environment has been destroyed. Comment |
Status update - IBM ROKS e2e validation in progressWhat's merged into this PRThe branch now contains all ADLC data model changes plus the e2e cleanup:
IBM ROKS e2e - blockers resolved during validationDeployed the new API server + control plane to hysh-ibm-01 and worked through several sequential blockers:
Remaining: chart/gateway image version mismatchThe openshell chart in this repo was bumped to v0.1.2 (PR #374) but the gateway images on the ROKS cluster are still at 0.0.109. The v0.1.2 chart generates a config structure ( This is a pre-existing infrastructure gap unrelated to the ADLC data model changes in this PR. The e2e gateway lifecycle test cannot pass until either:
The ADLC API kinds (AgentRuntime, SandboxTemplate, etc.) and the GatewayRelease/GatewayNetwork removal are independently correct and do not affect this infrastructure issue. |
Introduces specs/adlc/agents.spec.md, which defines the data model and requirements for running autonomous AI agents as first-class HyperShell API resources. New top-level kinds: AgentRuntime, SandboxTemplate, ProviderSpec, SecretSource. Workspace-scoped sub-resources: Workspace, WorkspaceMembership, ProviderBinding, InferenceRoute. Key design decisions captured in the spec: - Gateway-agnostic capability model: no OpenShell CLI flags or driver names appear in the API; the controller translates them. - ProviderSpec and SandboxTemplate are reusable across AgentRuntimes. - SecretSource purpose enum drives env var wiring without operator annotation. - ManifestWork delivers scheduling resources to target clusters via OCM. - Bootstrap Job provisions gateway-side workspace, members, and providers idempotently. - AgentRuntime owns exactly one Workspace (isolation primitive). Adds the ADLC section to specs/index.spec.md and registers adlc/agents.spec.md in the spec registry table. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…emove adlc/ The ADLC spec introduced AgentRuntime, SandboxTemplate, ProviderSpec, ProviderBinding, InferenceRoute, and SecretSource as a separate specs/adlc/ namespace. These are regular HyperShell API kinds reconciled by the existing controller - no architectural separation is warranted. Fold all kinds, ER entities, requirements, and design decisions into the existing specs/platform/data-model.spec.md alongside Gateway, GatewayNetwork, and ManagedCluster. Remove specs/adlc/ entirely. Two architectural corrections applied vs. the original ADLC draft: - No ManifestWork: the controller applies cluster resources directly, same as gateway infrastructure today. - No bootstrap Job: the controller provisions gateway-side workspace, members, and provider bindings via the gateway gRPC API in its normal reconcile loop, same as database provisioning. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Mark both kinds as Slated for Removal in the data model spec: - GatewayRelease: Gateway image/supervisor_image fields make the release indirection layer unnecessary; canary rollout was never adopted. - GatewayNetwork: The reconciler owns no K8s resources and only validates topology fields; real mesh/tunnel provisioning was never defined. Remove both from the ER diagram. Add deprecation banners to their requirement sections. Mark API routes, CLI sections, and hsctl apply rows as [REMOVED]. Add design decision rationale for both removals. Add 20 RM- gap items to skills/RECONCILE.md covering all 8 implementation layers (FE -> CLI -> CP -> BE+gRPC -> API+SDK -> DB) in reverse-dependency removal order. Extend skills/build/reconcile/SKILL.md with a Kind Removal Wave Pattern and skills/build/full-stack-pipeline/SKILL.md with a reverse-dependency execution note, so /reconcile can plan and execute kind deletion the same way it plans additions. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…kinds Remove GatewayRelease and GatewayNetwork across all implementation layers: - FE: deleted gateway-release-distribution-aggregation adapter + tests; removed GatewayRelease metric from dashboard-control-plane adapter - CLI: deleted 8 command dirs (create/get/list/delete for both kinds); removed URL constants, TUI kind enum entries, release selector from form - CP: deleted GatewayReleaseReconciler, GatewayNetworkReconciler, WatchGatewayReleases, WatchGatewayNetworks; removed release_id propagation from GatewayReconciler; watchCount 4->2 - BE: deleted plugins/gatewayReleases and plugins/gatewayNetworks; removed release_id/observed_release_id from Gateway model, handler, service, presenters; removed GatewayReleaseService+GatewayNetworkService from grpc_authorization.go - Proto: deleted gateway_releases.proto, gateway_networks.proto and generated stubs - API: deleted openapi.gatewayReleases.yaml, openapi.gatewayNetworks.yaml; removed release_id from openapi.gateways.yaml; cleaned openapi.yaml references - DB: added drop-table migrations for gateway_releases and gateway_networks tables; added drop-column migration for gateways.release_id/observed_release_id Add 6 new ADLC API kinds (REST layer, no CP watcher/reconciler yet): - AgentRuntime, SandboxTemplate, ProviderSpec, ProviderBinding, InferenceRoute, SecretSource - OpenAPI specs, models, DAOs, handlers, services, presenters, migrations, plugin registrations for all 6 kinds - Regenerated Go SDK (make generate) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
GatewayRelease and GatewayNetwork were removed from the data model in 6dcd9b8. This removes E2E_RELEASE_ID seeding, release_id from all gateway create payloads, and the corresponding lib_test.sh unit test assertions so the e2e suite runs cleanly against the new schema. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… e2e - gofmt fixes in reconciler.go, main.go, factory_test.go, inferenceRoutes/model.go - Regenerate sdk-typescript/src: add AgentRuntime, SandboxTemplate, ProviderSpec, ProviderBinding, InferenceRoute, SecretSource; remove GatewayRelease, GatewayNetwork - e2e area 13 (gateway release promotion): permanently skip since GatewayRelease and GatewayNetwork kinds were removed from the data model - Remove E2E_RELEASE_ID forwarding from e2e-performance.sh Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…e area 13 Seed scripts (kind, openshift) still created GatewayRelease resources and included release_id in gateway create bodies; these 400 with the new API server. Remove the GatewayRelease block and release_id field from both. Web console adapter still referenced gateway.release_id (ESLint no-unsafe-assignment) and the gateway create payload still sent release_id. Remove releaseId from GatewayRecord type, gateway-operations adapter, and all test/story fixtures. Remove the gatewayReleaseId message and en.json entry. e2e area 13 permanently skipped (GatewayRelease/GatewayNetwork removed). e2e-performance.sh E2E_RELEASE_ID forwarding removed. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
b26552e to
30225a6
Compare
… tests GatewayRelease was removed from the data model; remaining test assertions checking for release_id / release-1 cause CI failures in shell unit tests, frontend unit tests, and Playwright e2e. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Verdict
This PR removes GatewayRelease/GatewayNetwork and scaffolds six new ADLC API kinds (AgentRuntime, SandboxTemplate, ProviderSpec, ProviderBinding, InferenceRoute, SecretSource), but the removal stops at the Go model/DB layer and the new spec/code carry unresolved security and consistency gaps. I am requesting changes: the gRPC contract and control plane still carry the removed release fields, the spec still documents them as live while companion specs stay Active, the new REST resources list/get/delete across all tenants, and the coordinator pod spec omits a restricted SecurityContext. The latest commit only strips stale release_id test assertions, so every prior finding remains.
Findings
Major
1. GatewayRelease removal is incomplete across the gRPC contract and the control plane (components/api-server/proto/hypershell/v1/gateways.proto L29, L63, L97, L122; components/control-plane/internal/reconciler/reconciler.go L618, L640, L1106).
The model, REST surface, and DB migration drop release_id/observed_release_id, but the removal stops there. gateways.proto still declares release_id (field 5 on Gateway, field 4 on CreateGatewayRequest, field 5 on UpdateGatewayRequest) and observed_release_id (fields 25/22) - unlike fleet_id/database_id, which this same file retires with reserved, these numbers are left live, so the generated gateways.pb.go keeps them and the gRPC contract advertises fields the server now silently ignores. The control plane still carries the full observed-release machinery: advanceObservedRelease(... gw.GetObservedReleaseId(), gw.GetReleaseId()) on both provisioning paths (L618, L640), and advanceObservedRelease writes ObservedReleaseId back via UpdateGateway (L1106) - a write the handler now discards. gw.GetReleaseId() is always empty now, so this is dead code pointing at a deleted concept. Either finish the removal (reserve the proto fields, regenerate, delete the observed-release machinery) or keep the fields intentionally and document why. See existing thread r4198052241. Confidence: High.
2. Code removes release_id/GatewayRelease but data-model.spec.md still documents them as live, and the companion specs stay Active (specs/platform/data-model.spec.md L55, L218, L256, L272, L844).
The ER diagram still carries string release_id FK (L55) and string observed_release_id (L70); the create scenario still starts "GIVEN a valid cluster_id and release_id" (L218); the provisioning-fields prose still says release_id is optional and "when both are set, release_id takes precedence" (L256); and the client reference still lists Gateway release_id as implemented (L844). The spec contradicts the code shipped in the same PR. Separately, gateway-release-rollout.spec.md, gateway-release-reconciliation.spec.md, gateway-release-distribution.spec.md, and gateway-network-reconciliation.spec.md remain Status: Active and define these kinds as desired state, so /reconcile would re-generate exactly what this PR deletes; no RM- item deprecates them. See existing thread r4196462174. Confidence: High.
3. New ADLC REST resources list/get/delete all records with no tenancy scoping (components/api-server/plugins/agentRuntimes/handler.go L24-L74, and the sibling inferenceRoutes/providerSpecs/providerBindings/sandboxTemplates/secretSources handlers).
List calls generic.List with no per-subject/per-workspace filter; Get/Delete do existence-only checks. In isAuthorized/AuthorizeApi the new resource paths fall through to the final return hasGatewayCreator(bindings) (pkg/rbac/authorization.go L421) - no case was added for the new kinds - so any authenticated gateway-creator can list, read, and delete every AgentRuntime, ProviderBinding, SecretSource, etc. across all tenants. Contrast the gateways handler, which scopes List to the caller's RoleBindings per security.spec.md "Gateway Access Isolation", and the stated "AgentRuntime owns exactly one AgentWorkspace (isolation primitive)" goal. If intentional for the initial scaffold, call it out and track the scoping work; otherwise add binding-scoped filtering before these endpoints ship. See existing thread r4197331386. Confidence: Medium.
4. Coordinator CronJob pod omits the required restricted SecurityContext (specs/platform/data-model.spec.md L450-L465).
The "AgentRuntime Cluster Resource Provisioning" resource list mandates automountServiceAccountToken: false and a default-deny NetworkPolicy, but requires no restricted SecurityContext on the coordinator CronJob pod; a scan finds no runAsNonRoot/SecurityContext anywhere in the spec. CLAUDE.md and security.spec.md require runAsNonRoot: true, allowPrivilegeEscalation: false, and Capabilities.Drop: ["ALL"] on all pod specs. Add that requirement so the implementation inherits it. See existing thread r4195774763. Confidence: Medium.
5. Inference model not cross-referenced to openshell-inference-routing.spec.md (specs/platform/data-model.spec.md; specs/index.spec.md L31).
InferenceRoute/ProviderBinding are the declarative counterpart of the already-specified workspace inference route and credential-free sandbox model access in platform/openshell-inference-routing.spec.md, but that spec is still not referenced in the body and the registry Depends On for data-model.spec.md lists only managed-cluster-registration, openshell-gateway-service-accounts. Cross-reference it and declare the dependency so the two models do not drift. See existing thread r4195774747. Confidence: Medium.
Minor
6. WorkspaceMembership has no population path and no implementing component (specs/platform/data-model.spec.md L504-L515, L485).
L513-515 say "the API server creates or updates the WorkspaceMembership" and validates at least one admin membership (422 otherwise), while L485 says the controller provisions memberships via the gateway gRPC API. There is still no REST route, no apply kind, and no AgentRuntime field carrying member subjects/roles; the code adds plugins only for the six flat kinds (no workspaces/workspaceMemberships plugin), so the admin-membership validation has no owner. Specify where membership subject+role originate and which component owns create/update. See existing thread r4196236920. Confidence: Medium.
7. Pending definition reads as a slight mismatch with the create/reconcile scenario (specs/platform/data-model.spec.md L696, L462-465).
Pending is defined as "Created; reconciliation not yet started" (L696), while the reconcile scenario starts from a Pending AgentRuntime, runs the reconcile loop, and transitions to Provisioning (L462-465). Tighten the wording so the "not yet started" phrasing and the reconcile-from-Pending trigger clearly agree. Confidence: Low.
8. PR description is stale relative to the delivered change.
The body still describes a spec-only change introducing specs/adlc/agents.spec.md, OCM/ManifestWork delivery, and Workspace/WorkspaceMembership/ProviderBinding/InferenceRoute as sub-resources. The delivered change folds the model into data-model.spec.md, records "No ManifestWork" as the decision (L1043), removes two kinds across all layers, and adds six flat top-level kinds with full REST/SDK/CLI scaffolding. Update the description so reviewers and /reconcile see the actual scope. Confidence: High.
Cross-PR coordination
Three open pull requests take a direction that collides with this PR's removal of GatewayRelease/GatewayNetwork and need a maintainer decision plus a defined merge order:
- #412 reworks the Gateway create contract to placement intent while keeping
release_ida required create field: theGatewayCreateRequestrequiredlist becomesname, placement, release_id, andrelease_id/ReleaseIdstay on the OpenAPI model, the generated model, andgateways.proto. This PR deletesrelease_idfrom the create contract and deletes both kinds, editing the sameopenapi.gateways.yaml,gateways.proto/gateways.pb.go, andmodel_gateway_create_request.gowith opposite intent. Maintainers must decide whether the placement rework should also droprelease_id, and sequence the two so the create contract does not end up requiring a field the other PR removes. - #445 adds Go and TypeScript SDK columns to the exact
Gateway NetworksandGateway Releasesclient-reference rows this PR marks[REMOVED], documenting both kinds as a supported SDK surface in the samedata-model.spec.mdtable. Opposite intent on the same rows; maintainers must decide whether those SDK bindings should be documented at all given the removal, and order the two edits to that table. - #185 specifies net-new periodic control-plane inventory polling and explicitly lists
GatewayReleaseandGatewayNetworkas kinds the world-sync cycle must poll ("Adding inventory polling for Fleet, ManagedCluster, GatewayRelease, and GatewayNetwork is net-new control-plane work"). That builds new reconciler work on the two kinds this PR deletes. Maintainers must decide whether the world-sync scope should drop those kinds and in which order the two land.
Previous concerns
- Em dashes (r4195774738): Addressed.
specs/adlc/was removed; a U+2014 scan of the changed files returns no matches. - OCM/ManifestWork delivery divergence (r4195774755): Addressed. The controller applies cluster resources directly (
data-model.spec.mdL452) and the design-decision table records "No ManifestWork" (L1043). GatewayRelease/GatewayNetworkdeprecation inconsistent (r4196462174): Still present. See Finding 2 -data-model.spec.mdstill documentsrelease_idas live (L55, L256, L844) and the companion specs remainActive.- Restricted SecurityContext on generated pods (r4195774763): Still present. See Finding 4 - no SecurityContext on the coordinator
CronJob(L450-465). - Inference model duplicates
openshell-inference-routing.spec.md(r4195774747): Still present. See Finding 5 - no body reference, dependency absent fromindex.spec.mdL31. WorkspaceMembershippopulation path (r4196236920): Still present. See Finding 6 - no route/apply kind/field and no implementing plugin.- New ADLC REST resources lack tenancy scoping (r4197331386): Still present. See Finding 3 - unscoped
generic.Listand fall-through tohasGatewayCreator(authorization.goL421). GatewayReleaseremoval incomplete below the model/DB layer (r4198052241): Still present. See Finding 1 - proto fields still live, control-plane observed-release machinery intact.
Findings Summary
- [Major] GatewayRelease removal incomplete: proto + control plane still carry
release_id/observed_release_idafter the model/DB removed them - Spec/Code Consistency (gateways.proto L29, reconciler.go L618, L1106) - [Major] Code removes
release_id/GatewayReleasebut spec still documents them as live and companion specs stayActive- Spec Consistency (L55, L256, L844) - [Major] New ADLC REST resources list/get/delete all records with no tenancy scoping - Security / Isolation (agentRuntimes/handler.go L24-74, authorization.go L421)
- [Major] Coordinator
CronJobpod omits the required restricted SecurityContext - Security (L450-465) - [Major] Inference model not cross-referenced to
openshell-inference-routing.spec.md; dependency missing - Spec Consistency (data-model, index L31) - [Minor]
WorkspaceMembershiphas no population path and no implementing plugin - Spec Completeness (L504-515) - [Minor]
Pendingdefinition wording mismatches the create/reconcile scenario - Spec Completeness (L696, L462-465) - [Minor] PR description is stale relative to the delivered change - Process
Convention Checklist
| Convention | Result |
|---|---|
| No em dashes | Pass |
No panic() in new production code |
Pass |
Secret references, not inline secrets (SecretSource stores backend/path refs) |
Pass |
| DB migrations reversible (drop column has rollback) | Pass |
Test diff scrutiny (stale release_id assertions removed, no flipped guarantees) |
Pass |
| Removed kind leaves no dangling references across all layers (proto, control plane) | Fail |
| Restricted SecurityContext on all pod specs | Fail |
| Tenancy/RBAC scoping consistent with the gateway handler | Fail |
| Verify contracts and references before building on them (spec vs. code; inference xref) | Fail |
| Reconcile / idempotent (update-or-create) pattern | Pass |

Introduces specs/adlc/agents.spec.md, which defines the data model and requirements for running autonomous AI agents as first-class HyperShell API resources.
New top-level kinds: AgentRuntime, SandboxTemplate, ProviderSpec, SecretSource. Workspace-scoped sub-resources: Workspace, WorkspaceMembership, ProviderBinding, InferenceRoute.
Key design decisions captured in the spec:
Adds the ADLC section to specs/index.spec.md and registers adlc/agents.spec.md in the spec registry table.