Skip to content

feat(api): hosts/{id} enrichment — liveness + compliance summary (16/16 ACs)#428

Merged
remyluslosius merged 1 commit into
mainfrom
feat/api-hosts-enrichment
May 30, 2026
Merged

feat(api): hosts/{id} enrichment — liveness + compliance summary (16/16 ACs)#428
remyluslosius merged 1 commit into
mainfrom
feat/api-hosts-enrichment

Conversation

@remyluslosius
Copy link
Copy Markdown
Contributor

Summary

Extends `api-hosts` to v1.1.0. `GET /api/v1/hosts/{id}` now returns the host plus the two highest-value per-host views from Slice B: live reachability state and compliance roll-up.

`GET /api/v1/hosts` (list) is intentionally unchanged — keeps bulk-read cost flat. Enrichment is detail-only.

Spec changes (api-hosts 1.0.0 → 1.1.0)

New constraints:

  • `C-05` GET /hosts/{id} must include `liveness` (populated when probed; null otherwise)
  • `C-06` GET /hosts/{id} must include `compliance_summary` with passing/failing/skipped/error/total; empty rule_state → all zeros, never null/error

New ACs:

  • `AC-13` liveness populated when host_liveness has a row
  • `AC-14` liveness null when never probed
  • `AC-15` compliance_summary counts correct on mixed rule_state
  • `AC-16` compliance_summary all zeros on empty rule_state

OpenAPI shape

New schemas: `HostLiveness`, `HostComplianceSummary`, `HostDetailResponse`.

```json
{
"host": { ...HostResponse... },
"liveness": { "reachability_status": "reachable", "last_probe_at": "...", ... } | null,
"compliance_summary": { "passing": 2, "failing": 3, "skipped": 1, "error": 1, "total": 7 }
}
```

Verification

```
go vet ./... clean
go test -race -count=1 PASS (5.3s with Postgres)
specter parse PASS (api-hosts@1.1.0)
specter check PASS
specter coverage api-hosts 16/16 (100%)
```

Test plan

  • CI Quality + security gates pass
  • Confirm `api-hosts` reaches 100% in `specter coverage` (12 existing + 4 new = 16)
  • Manual smoke after merge: `curl .../api/v1/hosts/` and verify the envelope

…16 ACs)

Extends api-hosts to v1.1.0 by enriching GET /hosts/{id} with the
two highest-value per-host views from Slice B: live reachability
state and compliance roll-up. List endpoint (GET /hosts) unchanged
to keep bulk-read cost flat.

Spec (api-hosts 1.0.0 -> 1.1.0)
  New constraints:
    C-05  GET /hosts/{id} response MUST include liveness sub-object
          (populated when host_liveness has a row, null otherwise).
    C-06  GET /hosts/{id} response MUST include compliance_summary
          with passing, failing, skipped, error, total counts.
          Empty rule_state -> all zeros, never null or error.
  New ACs:
    AC-13 liveness populated when probed.
    AC-14 liveness null when never probed.
    AC-15 compliance_summary counts correct on mixed rule_state.
    AC-16 compliance_summary all zeros on empty rule_state.

OpenAPI schema additions
  HostLiveness          mirrors host_liveness columns + the
                        reachability_status enum.
  HostComplianceSummary five typed counters.
  HostDetailResponse    {host: HostResponse, liveness: HostLiveness?,
                        compliance_summary: HostComplianceSummary}.
  GET /hosts/{id} response switched from HostResponse to
  HostDetailResponse. PATCH/POST/DELETE responses unchanged.

Implementation
  - internal/server/hosts_enrichment.go: two helpers behind the
    handler.
      loadHostLiveness         LEFT-JOIN-style read; returns (nil,
                              nil) when no row exists so the
                              handler can encode liveness=null.
      loadHostComplianceSummary FILTER aggregate over
                              host_rule_state; always returns a
                              struct (zeros on empty).
  - internal/server/hosts_handlers.go: GetHostByID now fans out
    to the two helpers after the host fetch and wraps everything
    in HostDetailResponse.
  - internal/server/api_hosts_test.go: existing AC-08 + AC-10 tests
    updated to decode the new {host: {...}} envelope shape.
  - internal/server/api_hosts_enrichment_test.go: four new tests
    covering AC-13/14/15/16 against a real Postgres fixture.

Verification
  go vet ./...            clean
  go test -race -count=1  PASS (5.3s with Postgres)
  specter parse           PASS (api-hosts@1.1.0)
  specter check           PASS
  specter coverage        api-hosts 16/16 (100%)

Spec: app/specs/api/hosts.spec.yaml
@remyluslosius remyluslosius enabled auto-merge (squash) May 30, 2026 01:34
@remyluslosius remyluslosius merged commit dc8e42f into main May 30, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant