refactor(server): merge pkg/api into pkg/server, drop legacy direct handlers#1127
Conversation
…andlers
pkg/api's purpose (HTTP REST handlers) was conflated with the AICR API
spec at api/aicr/v1/server.yaml and the SDK at pkg/client/v1. Fold the
handlers into pkg/server (the only HTTP-serving binary) and route all
business logic through the pkg/client/v1 facade.
- Move handler files into pkg/server (allowlist, bundle, recipe, query,
openapi sync, version negotiation); rename server.go -> serve.go.
- Delete legacy direct-construction handlers superseded by the facade:
pkg/bundler/handler.go HandleBundles, pkg/recipe/handler.go,
pkg/recipe/handler_query.go. Resolves the import cycle that blocked
the merge.
- Preserve QueryRequest + ParseQueryRequestFromBody in
pkg/recipe/query_request.go (still used by the facade-backed handler).
- cmd/aicrd/main.go now calls server.Serve(); ldflags retargeted to
pkg/server.{version,commit,date} in .goreleaser.yaml and the
contract test in pkg/validator/catalog/catalog_test.go.
- Sync .claude/CLAUDE.md and AGENTS.md package tables, refresh
DEVELOPMENT.md, docs/contributor/api-server.md,
docs/contributor/api-server-extending.md, docs/contributor/index.md,
docs/integrator/public-api.md, .github/labeler.yml,
.github/PULL_REQUEST_TEMPLATE.md, .github/copilot-instructions.md,
and stale godoc references in pkg/recipe, pkg/logging, pkg/serializer,
pkg/evidence/attestation.
- Drop orphaned keyError const in pkg/bundler/bundler.go and rename
shadowed local version in pkg/server/version.go.
Sweep of doc.go and markdown after the pkg/api -> pkg/server merge and
the broader facade/recipe/collector evolution. Surgical edits only; no
rewrites or new top-level sections.
Root + DEVELOPMENT:
- README.md: Go Library entry now points to pkg/client/v1 (SDK facade).
- DEVELOPMENT.md: drop pkg/api from the directory tree, add
pkg/client/v1; pkg/server description rewritten; API endpoints list
filled in (/v1/recipe, /v1/query, /v1/bundle); CLI command list
expanded from 4 to the actual 11; bundle attestation noted as opt-in.
User docs: clean, no drift (verified against pkg/recipe/criteria.go,
pkg/errors, pkg/defaults, pkg/cli, pkg/server, api/aicr/v1/server.yaml,
recipes/registry.yaml).
Integrator docs:
- docs/integrator/index.md: added missing public-api.md + go-library.md
rows already linked from siblings.
- docs/integrator/go-library.md: MakeBundle timeout caveat documented
(opt-in via BundleOptions.Timeout, uncapped when zero).
Contributor docs:
- docs/contributor/api-server.md: handler paths and code samples now
reflect pkg/server/recipe_handler.go and the aicr.Client facade
(newRecipeHandler, ResolveRecipeFromCriteria, http.MaxBytesReader);
Internal Packages list includes pkg/client/v1 and pkg/bundler.
- docs/contributor/cli.md: dropped stale uninstall.sh from bundle output.
- docs/design/004-query-command.md: status flipped to Accepted and
Implemented; points to pkg/recipe/query.go and HandleQuery.
Core package doc.go (factual drift only):
- pkg/recipe: added CriteriaOSTalos to OS list.
- pkg/bundler: deployer list now covers helm, argocd, argocd-helm, flux,
helmfile, localformat; stale truncated component list dropped.
- pkg/bundler/config: Deployer types list completed.
- pkg/collector: Factory signature includes CreateNodeTopologyCollector;
subpackages list updated.
- pkg/collector/{file,k8s,os,systemd}: example code matches real API
(Parser with options, &Collector{} construction, singular Measurement).
- pkg/validator: RBAC composition corrected (ServiceAccount + per-run
ClusterRoleBinding to cluster-admin; constraints moved to pkg root).
- pkg/snapshotter: bogus Snapshotter interface dropped; AgentConfig and
RequireGPU fields added; partial-snapshot behavior accurately stated.
- pkg/evidence: attestation and verifier subpackages no longer "will
land" -- both exist.
- pkg/cli: Architecture notes facade delegation through pkg/client/v1;
pkg/component reframed as shared utilities.
- pkg/component: preamble notes registry-driven DefaultBundler replaces
per-component packages.
Utility package doc.go (factual drift only):
- pkg/header: Header struct shape and Kind constants match real types
(typed Kind, flat Metadata map[string]string).
- pkg/version: prerelease/build metadata moved to "Supported" (preserved
in Extras; not used for ordering).
- pkg/config: scope widened to snapshot/recipe/bundle/validate.
- pkg/oci: three -> four operations.
- pkg/build: documents BuildSpec schema + LoadSpec/Validate/WriteBack
primitives instead of overstated build pipeline.
- pkg/client/v1/aicr.go: Surface subsection enumerating the four
end-to-end operations (ResolveRecipe/LoadRecipe, BundleComponents,
CollectSnapshot, ValidateState).
Coverage Report ✅
Coverage BadgeMerging this branch will decrease overall coverage
Coverage by fileChanged files (no unit tests)
Please note that the "Total", "Covered", and "Missed" counts above refer to code statements instead of lines of code. The value in brackets refers to the test coverage of that file in the old version of the code. |
📝 WalkthroughWalkthroughThis PR consolidates the HTTP server implementation from Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 6
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
pkg/header/doc.go (1)
100-100:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winUpdate the validation bullet to
timestampterminology.Line 100 still says “Created timestamp,” but the updated header model/documentation uses
metadata["timestamp"]. Keeping this stale term makes the package docs internally inconsistent.As per coding guidelines, "Ensure code comments are accurate and helpful".✏️ Proposed doc fix
-// - Created timestamp is reasonable +// - Metadata timestamp is reasonable🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@pkg/header/doc.go` at line 100, Update the documentation bullet that currently reads "Created timestamp" to use the new `metadata["timestamp"]` terminology so docs match the header model; locate the validation bullet in pkg/header/doc.go referencing the created timestamp and replace the phrase with either "timestamp" or explicitly `metadata["timestamp"]` to reflect the updated header field naming.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@DEVELOPMENT.md`:
- Around line 195-196: Add a single blank line immediately before the "#### API
Server" heading in DEVELOPMENT.md to satisfy markdown lint rule MD022; locate
the heading text "#### API Server" and insert one empty line above it so the
heading is separated from the previous paragraph.
In `@docs/contributor/api-server.md`:
- Around line 36-40: Update the architecture diagram reference that still points
to pkg/server/server.go so it instead points to the current server entry
pkg/server/serve.go; locate the diagram nodes (A, B, B1, C) in
docs/contributor/api-server.md and change the C node label or link that
currently shows "pkg/server/server.go" to "pkg/server/serve.go" (and verify the
B node arrow to C remains B1 --> C).
In `@pkg/collector/k8s/doc.go`:
- Around line 57-58: The doc example directly constructs k8s.Collector with
&k8s.Collector{}; change it to use the collector factory and functional options:
create a factory with collector.NewDefaultFactory(...) (passing required
dependencies/config), then obtain the collector via the factory (e.g.,
factory.NewCollector(ctx, /* functional options */) or factory.New(ctx, /*
options */) depending on the factory API) and use that instance instead of
&k8s.Collector{} to align with the collector.NewDefaultFactory and
functional-options pattern.
In `@pkg/collector/os/doc.go`:
- Around line 54-55: Replace the direct struct construction (&os.Collector{})
with the package factory pattern: call collector.NewDefaultFactory(...) to
obtain a factory configured with the appropriate functional options, then use
the factory to create the collector instance (e.g. factory.NewCollector(...) or
factory.Create(...)) and call Collect on that instance; update the example code
to show creating the factory (collector.NewDefaultFactory(...)), instantiating
the collector from it, handling errors, and then calling collector.Collect(ctx)
instead of using os.Collector directly.
In `@pkg/collector/systemd/doc.go`:
- Around line 35-41: Replace direct struct literals of systemd.Collector with
the factory/options pattern: stop creating instances via &systemd.Collector{...}
and instead obtain them through the collector factory (e.g.,
collector.NewDefaultFactory or the package's factory function) and pass service
names via the provided functional options; update both documented examples that
currently instantiate systemd.Collector directly to call the factory (e.g.,
collector.NewDefaultFactory(...) or systemd.NewWithOptions(...)) and supply
Services using the option helpers so the docs show the required collector
initialization contract.
In `@pkg/server/doc.go`:
- Around line 30-42: The documented middleware chain in pkg/server/doc.go is out
of order; update the comment to match the repository standard by listing
middleware in the order used by the server: metricsMiddleware →
versionMiddleware → requestIDMiddleware → panicRecoveryMiddleware →
rateLimitMiddleware → loggingMiddleware → handler (i.e., metrics, version,
requestID, panic, rateLimit, logging, then the actual handler), ensuring you
reference the exact middleware names (metricsMiddleware, versionMiddleware,
requestIDMiddleware, panicRecoveryMiddleware, rateLimitMiddleware,
loggingMiddleware) so docs and implementation guidance are aligned.
---
Outside diff comments:
In `@pkg/header/doc.go`:
- Line 100: Update the documentation bullet that currently reads "Created
timestamp" to use the new `metadata["timestamp"]` terminology so docs match the
header model; locate the validation bullet in pkg/header/doc.go referencing the
created timestamp and replace the phrase with either "timestamp" or explicitly
`metadata["timestamp"]` to reflect the updated header field naming.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Enterprise
Run ID: 7d4b24dd-b2bb-405e-8989-5589824eedf2
📒 Files selected for processing (61)
.claude/CLAUDE.md.github/PULL_REQUEST_TEMPLATE.md.github/copilot-instructions.md.github/labeler.yml.goreleaser.yamlAGENTS.mdDEVELOPMENT.mdREADME.mdcmd/aicrd/main.godocs/contributor/api-server-extending.mddocs/contributor/api-server.mddocs/contributor/cli.mddocs/contributor/index.mddocs/design/004-query-command.mddocs/integrator/go-library.mddocs/integrator/index.mddocs/integrator/public-api.mdpkg/api/bundle_handler_test.gopkg/api/doc.gopkg/build/doc.gopkg/bundler/bundler.gopkg/bundler/config/doc.gopkg/bundler/doc.gopkg/bundler/handler.gopkg/bundler/handler_test.gopkg/cli/doc.gopkg/client/v1/aicr.gopkg/collector/doc.gopkg/collector/file/doc.gopkg/collector/k8s/doc.gopkg/collector/os/doc.gopkg/collector/systemd/doc.gopkg/component/doc.gopkg/config/doc.gopkg/evidence/attestation/emit.gopkg/evidence/doc.gopkg/header/doc.gopkg/logging/doc.gopkg/oci/doc.gopkg/recipe/doc.gopkg/recipe/handler.gopkg/recipe/handler_query.gopkg/recipe/handler_query_test.gopkg/recipe/handler_test.gopkg/recipe/query_request.gopkg/serializer/doc.gopkg/server/allowlist.gopkg/server/bundle_handler.gopkg/server/bundle_handler_test.gopkg/server/consts.gopkg/server/doc.gopkg/server/openapi_sync_test.gopkg/server/recipe_handler.gopkg/server/recipe_handler_test.gopkg/server/serve.gopkg/server/serve_test.gopkg/server/version.gopkg/snapshotter/doc.gopkg/validator/catalog/catalog_test.gopkg/validator/doc.gopkg/version/doc.go
💤 Files with no reviewable changes (9)
- docs/contributor/api-server-extending.md
- pkg/api/bundle_handler_test.go
- pkg/recipe/handler.go
- pkg/recipe/handler_query.go
- pkg/api/doc.go
- pkg/bundler/bundler.go
- pkg/recipe/handler_test.go
- pkg/bundler/handler_test.go
- pkg/recipe/handler_query_test.go
- DEVELOPMENT.md: add blank line after "API Server" heading (MD022).
- pkg/collector/{k8s,os,systemd}/doc.go: switch example code from
direct &Collector{} construction to the canonical
collector.NewDefaultFactory() factory pattern (with
WithSystemDServices option for the systemd example).
- pkg/server/doc.go: rewrite middleware chain section to match the
actual outermost-to-innermost order in Server.withMiddleware
(metrics, version, requestID, timeout, logging, panicRecovery,
rateLimit, bodyLimit).
CodeRabbit suggestion on docs/contributor/api-server.md diagram
intentionally skipped: pkg/server/server.go still exists (Server
struct + Run live there) and is correctly distinct from
pkg/server/serve.go (Serve entry point).
CodeRabbit out-of-diff finding on PR #1127: the godoc "Validation" bullet still said "Created timestamp" although Header now stores the value at metadata["timestamp"] (lowercase, flat map). Match the bullet to the actual field name.
|
Addressed the out-of-diff finding on pkg/header/doc.go in bb1ed52 — "Created timestamp" → "Metadata["timestamp"]" to match the actual field name. All inline comments from the original review are now resolved. |
There was a problem hiding this comment.
♻️ Duplicate comments (1)
pkg/server/doc.go (1)
30-44:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winMiddleware order in docs conflicts with repository standard.
This section documents
loggingMiddlewarebeforepanicRecoveryMiddlewareandrateLimitMiddleware, which diverges from the requiredmetrics → version → requestID → panic → rateLimit → logging → handlerorder.As per coding guidelines: "
pkg/server/**/*.go: Add middleware in order: metrics → version → requestID → panic → rateLimit → logging → handler".🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@pkg/server/doc.go` around lines 30 - 44, The doc comment lists middleware in the wrong order; update the middleware chain description to match the repo standard ordering: metricsMiddleware → versionMiddleware → requestIDMiddleware → panicRecoveryMiddleware → rateLimitMiddleware → loggingMiddleware → (handler) and ensure any surrounding entries like timeoutMiddleware and bodyLimitMiddleware are placed consistently relative to that sequence; edit the comment that mentions loggingMiddleware, panicRecoveryMiddleware, and rateLimitMiddleware in pkg/server/doc.go so the list matches the exact middleware symbol names (metricsMiddleware, versionMiddleware, requestIDMiddleware, panicRecoveryMiddleware, rateLimitMiddleware, loggingMiddleware) and reflects that they are applied outermost-to-innermost before the handler.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Duplicate comments:
In `@pkg/server/doc.go`:
- Around line 30-44: The doc comment lists middleware in the wrong order; update
the middleware chain description to match the repo standard ordering:
metricsMiddleware → versionMiddleware → requestIDMiddleware →
panicRecoveryMiddleware → rateLimitMiddleware → loggingMiddleware → (handler)
and ensure any surrounding entries like timeoutMiddleware and
bodyLimitMiddleware are placed consistently relative to that sequence; edit the
comment that mentions loggingMiddleware, panicRecoveryMiddleware, and
rateLimitMiddleware in pkg/server/doc.go so the list matches the exact
middleware symbol names (metricsMiddleware, versionMiddleware,
requestIDMiddleware, panicRecoveryMiddleware, rateLimitMiddleware,
loggingMiddleware) and reflects that they are applied outermost-to-innermost
before the handler.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Enterprise
Run ID: 3efb178f-2a1e-4945-9b71-09a6221201f2
📒 Files selected for processing (6)
DEVELOPMENT.mdpkg/collector/k8s/doc.gopkg/collector/os/doc.gopkg/collector/systemd/doc.gopkg/header/doc.gopkg/server/doc.go
Summary
Folds
pkg/apiintopkg/serverso the HTTP handlers live next to the only binary that serves them (aicrd), and routes all business logic through thepkg/client/v1facade. Updates package godoc and contributor docs to match.Motivation / Context
pkg/apipurpose (HTTP REST handlers) was being conflated with the AICR API spec atapi/aicr/v1/server.yamland the SDK atpkg/client/v1. The package name was a navigation trap — three distinct concepts under three nearly identical labels. There is no second HTTP-serving binary planned andpkg/serveris not meant for reuse, so a flat merge is the simplest fix.Fixes: N/A
Related: N/A
Type of Change
Component(s) Affected
cmd/aicrd,pkg/server)pkg/recipe)pkg/bundler,pkg/component/*)docs/,examples/)Implementation Notes
Commit 1 —
refactor(server): merge pkg/api into pkg/server, drop legacy direct handlers:pkg/server(allowlist, bundle, recipe, query, openapi sync, version negotiation);server.gorenamed toserve.go.pkg/bundler/handler.goHandleBundles,pkg/recipe/handler.go,pkg/recipe/handler_query.go— these were superseded by the facade and were the source of the import cycle that blocked the merge.QueryRequest+ParseQueryRequestFromBodypreserved inpkg/recipe/query_request.go(still used by the facade-backed handler).cmd/aicrd/main.gonow callsserver.Serve(); ldflags retargeted topkg/server.{version,commit,date}in.goreleaser.yamland the contract test inpkg/validator/catalog/catalog_test.go..claude/CLAUDE.mdandAGENTS.mdpackage tables synced;DEVELOPMENT.md,docs/contributor/api-server*.md,docs/contributor/index.md,docs/integrator/public-api.md,.github/labeler.yml,.github/PULL_REQUEST_TEMPLATE.md,.github/copilot-instructions.md, and stale godoc references inpkg/recipe,pkg/logging,pkg/serializer,pkg/evidence/attestationrefreshed.keyErrorconst inpkg/bundler/bundler.goand rename shadowed localversioninpkg/server/version.go.Commit 2 —
docs: align package godoc and contributor docs with current state:Sweep of 26 doc.go and markdown files (surgical edits only) to bring them in line with the merged server, the
pkg/client/v1facade evolution, the per-field union validator merge, and the dropped per-component bundlers. Highlights:README.mdGo Library entry now points topkg/client/v1;DEVELOPMENT.mddirectory tree and CLI command list updated;pkg/header,pkg/version,pkg/config,pkg/builddoc.go rewrites to match real types/APIs; collector example code corrected to construct via&Collector{}and return singular*Measurement;pkg/snapshotterpartial-snapshot behavior accurately stated; ADR-004 (query command) flipped to Accepted and Implemented.Testing
go build ./...cleangolangci-lint run -c .golangci.yaml ./...— 0 issues-count=1make check-agents-syncpasses (CLAUDE.md / AGENTS.md from line 5 onward match)Risk Assessment
Rollout notes: Internal-only refactor; no API surface change.
pkg/apiis gone — external Go callers should already be usingpkg/client/v1(the documented stable surface).Checklist
make testwith-race)make lint)git commit -S)