The Credential view lists the account Secrets of the namespace by label
and skips any no live HelmRelease owns, so no kind is served until its
definition carries a credentials block. A mint replaces the stored value
in one conditional write keyed on the Secret's resourceVersion and
returns the plaintext once; a revoke discards it. Both record an Event
on the application, which needs create on events.
The application registry seeds an account Secret per declared account
before it writes the HelmRelease, so the chart can reference them from
the first render, prunes the Secrets of removed accounts after the
write, and refuses to delete an application whose release is suspended,
since Flux skips the uninstall and would leave the database running
with the Secrets gone. The ApplicationDefinition reconciler computes
the per-account valuesFrom entries with the function the API uses, so a
release that predates the block gets them on its next reconcile. Schema
defaulting moves to a package both can import.
A definition declaring a format or an account source that is not built
leaves its kind unserved rather than served with passwords the API
cannot issue. Tenant roles gain get and list on credentials at view and
create on mint and revoke at admin and for the tenant ServiceAccount.
Attribution comes from the kube-apiserver audit log, so the operations
docs get a policy for distributions that ship none, and
monitoring-agents a value for an extra fluent-bit output so a SIEM can
receive the log without dropping the VictoriaLogs outputs.
Assisted-by: LLM
Signed-off-by: Timofei Larkin <lllamnyp@gmail.com>
The gate read a name declaration only when it was an object, and diffed
only the constraint keywords it knew. A declaration turned into a string
or null, or a misspelled keyword, therefore looked like no change at
all. Those are exactly the inputs on which the API server refuses every
create of the kind, the harshest outcome a schema change can have.
The gate now runs a changed declaration through the same parser the
server uses and reports it when it cannot be enforced.
Assisted-by: LLM
Signed-off-by: Timofei Larkin <lllamnyp@gmail.com>
An application declares the limits on its own metadata.name at the
root of its schema, beside properties, where the gate's walk over spec
never looked. A chart lowering its name cap or adding a pattern rejects
names its previous release accepted, which is the same break as
tightening a spec field, so the gate reports it the same way.
Assisted-by: LLM
Signed-off-by: Timofei Larkin <lllamnyp@gmail.com>
branch-review on #3184 measured a real regression: switching CRD/
APIService discovery to content-based scanning made every file in
packages/+internal a candidate, and each was split into documents and
fully unmarshaled twice — once per parser — inflating a full snapshot
load from ~0.5s to ~3.4s.
Split each file's documents once and probe each document's kind once
before deciding which shape to try, so the common case (a document
that is neither a CRD nor an APIService — the overwhelming majority
of what the wider walk now sees) pays for at most one parse attempt
instead of two. Add a raw substring fast-reject, at both the
per-document and whole-file level, ahead of any YAML parsing: neither
kind this package cares about can appear without its own name
appearing as a literal substring first.
Also fixes two smaller gaps flagged in the same review: an untrusted
PR head checkout could point discovery at an arbitrarily large file
with no size guard (capped at 8 MiB), and a group's merged APIService
resource only recorded the first contributing file's path, dropping
the others from the report.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Timofei Larkin <lllamnyp@gmail.com>
Shadow-observation of the merged gate found a real miss: a CRD shipped
inside a chart's templates/ dir (guarded by a Helm {{- if }}) was
invisible because discovery was gated on directory name (crds/,
definitions/, manifests/), and a group served only by an external
aggregated apiserver (kind: APIService, no CRD, no vendored Go types)
had no representation at all.
Switch CRD/APIService discovery from directory-name to content
sniffing, and tolerate Helm directive lines sharing a document with
otherwise-valid YAML (the closing `{{- end }}` of a wrapping
conditional has no leading `---`, so it lands in the same document as
the manifest). Add a fourth source, SourceAPIService, reusing the
existing empty-schema mechanism so a first-party group's first
APIService appearance requires review without pretending to diff a
schema that lives outside this repository.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Timofei Larkin <lllamnyp@gmail.com>
childSchemas now recurses into items/additionalProperties whenever head defines a schema, diffing against an empty base when base had none. This catches constraining a previously-unconstrained array element or map value (base absent/true -> schema), while still treating additionalProperties:false -> schema and schema removal as safe relaxations.
Also tighten the first-party group check to cozystack.io and its dot-delimited subdomains so a lookalike like fakecozystack.io is not gated. Both covered by tests.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Timofei Larkin <lllamnyp@gmail.com>
Scope the gate's own files (cmd/api-gate, internal/apigate, the workflow) to the API owners in CODEOWNERS, and compile the detector from the trusted base checkout when present (head fallback only during bootstrap), so a PR cannot neuter the gate by editing its own detector code.
Detect two more breaking vectors: removing nullable:true (rejects null) and adding a oneOf/allOf/not composition constraint. Both covered by regression tests.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Timofei Larkin <lllamnyp@gmail.com>
Fix schema-diff correctness: guard nil head on removed child schemas, flag adding a type to a previously-unconstrained field, stop reporting a head becoming unconstrained as narrowing, detect additionalProperties:false, and only recurse items/additionalProperties when both sides carry a schema.
Gate resource and group removal as new categories. Filter CRD versions to served ones so the deprecation flow surfaces as a removed version, and flag added x-kubernetes-validations (CEL) rules. Discover first-party cozystack.io CRDs by walking crds/ and definitions/ dirs so a relocated CRD (e.g. cozystack-scheduler) is covered, and error on an empty snapshot. Surface unmapped apiserver storage prefixes and allow hyphens in plurals; drop Markdown from text-mode reports.
Workflow: diff against the true merge base, count only each reviewer's latest review on the current head commit, and scope the token to the approval step with persist-credentials:false.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Timofei Larkin <lllamnyp@gmail.com>
Add a deterministic api-gate tool (cmd/api-gate, internal/apigate) and a workflow that require an approving review from an API owner (lllamnyp or kvaps) when a PR introduces a new API group, a new resource, or a breaking schema change to an existing resource.
Detection diffs the checked-in OpenAPIv3 schemas (apps cozyrds + CRD manifests) and the apiserver storage registrations; no network or LLM calls.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Timofei Larkin <lllamnyp@gmail.com>