Skip to content

Estate-wide resource search (ADR-0025) #249

Description

@eth-man

Design settled in a grilling session; decisions and their reasoning are in ADR-0025 (#248). This is the build spec.

The gap

The console describes intent thoroughly — every class on a node, which group set it, why that group matched, the document it will be served (#141–#143). It has never described the result. PuppetDB indexes every resource in every catalog with parameters, manifest file and line; we query six of its endpoints and /resources is not one of them.

The question this exists to answer is not "what is this resource" but "do all these nodes agree about it".

Shape

Estate-wide search, new top-level Resources nav item, peer to Nodes. Live PuppetDB query, never projected. Results lead with variance:

File[/etc/ssh/sshd_config]      190 nodes    2 variants  ⚠
File[/etc/resolv.conf]          190 nodes    1 variant   ✓

Grouped by (type, title), distinct-hash count as the variant count, odd ones out sorted to the top. Consistency is computed from PuppetDB's resource field — a SHA-1 of type, title and parameters — so variance is established with no parameter crossing the wire.

Acceptance criteria

Query and safety

  • A search with no type is refused. (Mirrors listFacts: an empty allow-list fetches nothing, not everything.)
  • A count query runs before the fetch; above the render threshold the operator is told how many matched and asked to narrow, rather than the browser being handed a set it cannot draw.
  • The list query uses PQL extract and omits parameters. A test asserts parameters is absent from list results — this is a disclosure control, not an optimisation.
  • All queries built by PqlBuilder from a typed, Zod-validated filter. No interpolation.
  • PuppetDB unreachable renders the existing explicit state with last contact time.

Consistency

  • Variant count is distinct resource hashes within a (type, title) group.
  • Variance is counted within an environment and never across. A development node differing from a production node is not variance.
  • A test asserts the hash actually covers parameters, against a real PuppetDB response rather than a fixture. If this ever stopped being true the view would report agreement that does not exist — the most dangerous way this can fail.

Expansion

  • Expanding fetches parameters for one representative node per distinct hash, not one per node.
  • Variants shown side by side with differing keys highlighted.

Composition

Authorization and audit

  • New resources:read permission. Does not share inventory:read. Not implied by any existing role; nobody holds it until granted.
  • Expanding parameters writes an AuditLog row.
  • A parameter-filtered query writes an AuditLog row.
  • Ordinary browsing (type/title search, list view) writes nothing — burying the events that matter under the ones that do not is the failure mode.
  • Read audit rows carry null before/after and join no transaction. Forwarding must tolerate them.

Explicitly not in v1

Saved resource queries · CSV export · per-node catalog browser · exported-resource handling beyond surfacing the flag. All additive later without rework.

Notes for whoever builds it

resources:read is privileged by design. ADR-0025 §5 states plainly that parameter filtering is a disclosure oracle — a holder can confirm a secret by guessing without any value being rendered. A safe-list of "non-sensitive" parameter names was considered and rejected as incomplete-by-construction and actively misleading. Do not add one; the audit trail is the compensating control.

Two facts were verified against the live production PuppetDB before the design was fixed: extract genuinely omits parameters, and ["extract", [["function","count"]], …] works.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions