Skip to content

feat: Activity capability integration + query ergonomics (M6)#35

Merged
ecv merged 1 commit into
mainfrom
feat/m6-audit-query
Jun 4, 2026
Merged

feat: Activity capability integration + query ergonomics (M6)#35
ecv merged 1 commit into
mainfrom
feat/m6-audit-query

Conversation

@ecv

@ecv ecv commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Part of #34 (final milestone, M6, of the physical-inventory plan #15). This PR does not close #34 — the milestone also covers PolicyPreview fixtures, the printer-column/topology audit, and confirming the activity-scoping model, tracked below.

Makes inventory auditable (who changed what, when) and queryable for operators, via the platform Activity capability + kubectl-style query ergonomics. Scope is the milo-os/inventory repo only; client work is downstream (already filed + linked, see below).

What's in this PR

Audit — Activity capability integration

  • ActivityPolicy per kind (12) under config/milo/activity/policies/ + kustomization.yaml. Each has audit rules (create / update / delete, ordered specific→fallback, system: users excluded, referencing real spec/objectRef fields) and two event rules keyed on the inventory.miloapis.com/event-type annotation. Mirrors the dns-operator / network-services-operator layout.
  • Controller event emission — all 12 controllers emit best-effort events.k8s.io/v1 Events on Ready transitions: Normal Ready and Warning NotReady (carrying the specific condition reason, e.g. ProviderNotFound). Events are emitted in addition to conditions. Shared EventRecorder in internal/controller/events.go (mirrors conditions.go); one emit call sits in each controller's status-patch path, so it fires on every exit — including the initial reference-NotFound state, so create-then-resolve lifecycles read cleanly. Display values ride in inventory.miloapis.com/-prefixed annotations to keep CEL templates simple. Failures are logged and swallowed.
  • RBAC — controller gains create;patch on events.k8s.io Events (regenerated role.yaml).
  • Deploymentconfig/milo is a kustomize Component pulled in by milo-integration (policies only ship where the Activity system runs). POD_NAME wired via downward API for ReportingInstance. Validated: kustomize build through the milo-integration path renders all 12 policies.

Query — ergonomics for operators

  • docs/querying-and-activity.md — operator guide: kubectl/datumctl get columns, topology.inventory.miloapis.com/* label selectors, and reading inventory activity (datumctl activity query --filter CEL examples + a worked CircuitProvider lifecycle matching the exit criteria).

Tests

  • Unit tests for the Ready-transition gate and Event construction (annotations, reason/type, regarding, nil-safety, error swallowing). go test ./internal/controller/ (full envtest suite, 53 specs) passes; emission is a no-op when no recorder is wired, so existing specs are unchanged.

Design decisions settled here

  • Activity scoping for cluster-scoped infra objects — inventory kinds are cluster-scoped with no project owner. Events for them are created in the default namespace (Kubernetes convention for cluster-scoped subjects; overridable via INVENTORY_ACTIVITY_NAMESPACE); regarding points at the cluster-scoped object. Activities surface to staff/operators (platform-scoped), not per-project surfaces. Still needs confirmation with the Activity service owners — the one genuine unknown.
  • Event vs. condition parity — kept in sync through a single helper; conditions stay machine-readable, events feed timelines.

Remaining M6 work (not in this PR; #34 stays open until done)

  • PolicyPreview fixtures per policy (audit CRUD + event rules) — validate against a live Activity API.
  • envtest spec asserting Events actually land on transitions (helper is unit-tested; suite wires controllers without a recorder today).
  • Printer-column gap pass (all kinds already carry columns from M1–M5; needs a confirming audit).
  • Topology-label uniformity: Site/Cluster/Node/NetworkDevice/Link/Port/VirtualMachine propagate topology.*; Cable and Circuit do not — these are connective assets that can span topology, so single-value labels may not fit. Needs a decision rather than a blind fill.
  • Indexer audit (18 ref indexers registered; appears complete — confirm).
  • Confirm activity scoping model with Activity service owners.

Downstream (already filed + linked off #34)

🤖 Generated with Claude Code

Make inventory auditable and queryable for operators (issue #34, the final
milestone of #15).

Audit — platform Activity capability:
- ActivityPolicy per inventory kind (12) under config/milo/activity/policies/,
  with audit rules (create/update/delete, ordered specific→fallback, system
  users excluded) and event rules keyed on the inventory.miloapis.com/event-type
  annotation. Mirrors the dns-operator / network-services-operator layout.
- Controllers now emit best-effort events.k8s.io/v1 Events on Ready
  transitions (Normal "Ready", Warning "NotReady" carrying the specific
  condition reason). Events feed human-readable timelines; conditions remain
  the machine-readable status. Shared EventRecorder helper in
  internal/controller/events.go (mirrors conditions.go); a single emit call in
  each controller's status-patch path covers every exit, including the initial
  reference-NotFound state so create-then-resolve lifecycles read cleanly.
- Display values are carried in inventory.miloapis.com/-prefixed annotations so
  CEL summary templates stay simple.
- RBAC: controller gains create;patch on events.k8s.io Events.
- Deployment: config/milo is a kustomize Component pulled in by the
  milo-integration component (policies only ship where the Activity system
  runs); POD_NAME wired via downward API for ReportingInstance.

Query — operator ergonomics:
- docs/querying-and-activity.md: operator guide for kubectl/datumctl queries,
  topology label selectors, and reading inventory activity (CEL filter
  examples + a worked Circuit→Provider lifecycle).

Tests:
- Unit tests for the Ready-transition gate and event construction
  (annotations, reason/type, regarding, nil-safety, error swallowing).
- Existing envtest suite passes unchanged (emission is a no-op when no
  recorder is wired).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ecv ecv marked this pull request as ready for review June 3, 2026 21:48
@ecv ecv requested a review from scotwells June 3, 2026 21:48
@ecv

ecv commented Jun 3, 2026

Copy link
Copy Markdown
Contributor Author

how's my driving @scotwells

@ecv ecv merged commit fddd4c7 into main Jun 4, 2026
3 checks passed
@ecv ecv deleted the feat/m6-audit-query branch June 4, 2026 18:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

M6: Audit & query (Activity capability + query ergonomics)

2 participants