Skip to content

feat(hub-shim): label runs with their application and filter on it - #7

Closed
ibolton336 wants to merge 2 commits into
docs/adr-renumber-0009-0010from
feat/application-label
Closed

feat(hub-shim): label runs with their application and filter on it#7
ibolton336 wants to merge 2 commits into
docs/adr-renumber-0009-0010from
feat/application-label

Conversation

@ibolton336

@ibolton336 ibolton336 commented Aug 5, 2026

Copy link
Copy Markdown
Owner

Closes #3. Stacked on #6 (ADR renumber) — merge that first.

The problem

An application-scoped run carried its application only in spec.env as
APP_ID. So "which runs belong to application 42?" has no server-side answer:
a client fetches every run and scans spec.env, which is exactly what the
UI's per-application drawer does today. Fine at demo scale, wrong at inventory
scale, and it sits on the path of every per-application view.

The shape

konveyor.io/application: "<hub id>" stamped at create time on both AgentRun
and AgentWorkflowRun, and ?application=<id> on both run lists, served as a
label selector the apiserver evaluates.

The label is additive to APP_ID, not a replacement. The two carry the
same value to different consumers and neither can do the other's job:

carrier consumer why it can't be the other
APP_ID spec.env the pod — harness resolves from Hub at runtime env vars aren't indexable
konveyor.io/application metadata.labels the APIclient.List() selector a label isn't visible in the container

That framing is the whole proposal: upstream ADR 0006 says "the application ID
goes directly on the CR as an env var" and "other resource types are listed
unfiltered". It isn't wrong about the env var — it's using one carrier for two
jobs.

Decisions worth citing

  • uint64-bounded ids do double duty. Hub ids must parse as a uint64
    (hub.ParseAppID requires it), capping them at 20 digits — inside the
    apiserver's 63-char label-value limit. One bounded check pre-empts both a
    run the harness would reject at startup and a create the apiserver would
    reject outright. The check moved to invalidApplicationIdReason() and now
    also guards the AgentWorkflowRun create path, which previously had none.
    (Second commit: review on 📖 ADR 0006 — application id as a queryable label, not only an env var konveyor/agentic-controller#105 caught that a
    plain digits regex is weaker than the harness — a 21-digit id passed the
    shim and overflowed ParseUint at startup. Now an exact BigInt bound.)
  • An unhonourable filter is a 400, never a silent pass. Ignoring
    ?application= returns every run, which a per-application view renders as
    "these all belong to 42" — a wrong answer that looks like a right one.
  • Pre-label runs are not selected. A filtered list is "runs we can prove
    belong to 42", not "every run that ever touched 42". Pinned by a test.
  • BadRequestError now maps to 400 at the top-level catch (was 500).

Known gap

The controller builds each stage AgentRun's labels from scratch rather than
inheriting the parent's, so workflow stage runs don't carry the label
/api/agentruns?application=42 finds single runs only. Upstream controller
change; flagged in the ADR 0006 amendment.

Verification

End-to-end against a real kube-apiserver (envtest binaries, no cluster — the
default kubeconfig context is a shared demo cluster). Label stored,
kubectl -l konveyor.io/application=42 selects correctly at the apiserver,
pre-label runs excluded, all four 400 paths. dev/application-filter-smoke.ts
(npm run smoke:appfilter) is the reusable version — it discovers its own
fixtures and deletes the runs it creates.

Contract recorded in ADR 0009's route table and ADR 0010's label section; the
matching amendment to upstream ADR 0006 is filed separately.

🤖 Generated with Claude Code

ibolton336 and others added 2 commits August 5, 2026 11:54
Closes #3.

An application-scoped run carried its application only in spec.env as
APP_ID, so "which runs belong to application 42?" had no server-side
answer — a client had to fetch every run and scan spec.env, which is what
the UI's per-application drawer does today. Fine at demo scale, wrong at
inventory scale, and on the path of every per-application view.

Stamp konveyor.io/application: "<hub id>" at create time on both AgentRun
and AgentWorkflowRun, and serve ?application=<id> on both run lists as a
label selector the apiserver evaluates.

The label is additive to APP_ID, not a replacement: the env var is how the
pod learns its application (the harness resolves from Hub at runtime), the
label is how the API indexes runs. An env var is not indexable; a label is
not visible inside the container.

Three things worth calling out:

- The numeric-id check moves to invalidApplicationIdReason() and now also
  guards the AgentWorkflowRun create path, which had none. That path gains
  a 400 for non-numeric Hub ids — previously the apiserver would have
  rejected the create outright once a label carried the value.
- ?application= on a resource that cannot honour it is a 400, not a silent
  pass. An ignored filter returns every run, which a per-application view
  renders as "these all belong to 42" — a wrong answer that looks right.
- BadRequestError now maps to 400 at the top-level catch rather than
  falling through to 500.

Known gap: the controller builds each stage AgentRun's labels from scratch
instead of inheriting the parent's, so workflow stage runs do not carry
the label and ?application= on /api/agentruns finds single runs only.
That needs an upstream controller change.

Verified end-to-end against a real kube-apiserver (envtest binaries, no
cluster): label stored, kubectl -l selects correctly, pre-label runs
excluded, all four 400 paths. dev/application-filter-smoke.ts
(npm run smoke:appfilter) is the reusable version.

ADR 0009's route table and ADR 0010's label section record the contract;
the matching amendment to upstream ADR 0006 is filed separately.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Review on the upstream ADR amendment (konveyor/agentic-controller#105)
caught a real gap: the guard's /^\d+$/ accepted any digit string, but the
harness's hub.ParseAppID is strconv.ParseUint(s, 10, 64) — a 21-digit id
passed the shim and then killed the run at startup, the exact doomed-run
class the guard exists to pre-empt. Unbounded digits could also exceed the
apiserver's 63-char label-value limit.

invalidApplicationIdReason now rejects values above uint64 max (BigInt
compare, exact at the boundary: ...551615 valid, ...551616 rejected).
Smoke gains the overflow reject case; ADR 0010's claim is restated with
the bound that makes it true.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@ibolton336
ibolton336 deleted the branch docs/adr-renumber-0009-0010 August 5, 2026 16:38
@ibolton336 ibolton336 closed this Aug 5, 2026
ibolton336 added a commit that referenced this pull request Aug 5, 2026
Squash of PR #7 (feat/application-label), landed by direct merge after
the base-branch deletion on #6's merge auto-closed the PR.

Stamp konveyor.io/application at create time on AgentRun and
AgentWorkflowRun; serve ?application=<id> on both run lists as an
apiserver label selector. Ids are uint64-bounded (hub.ParseAppID
parity), not just digits. BadRequestError maps to 400 at the top-level
catch. Smoke: npm run smoke:appfilter.

Closes #3

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@ibolton336
ibolton336 deleted the feat/application-label branch August 5, 2026 16:42
@ibolton336

Copy link
Copy Markdown
Owner Author

Landed on main as daab736 via direct squash-merge — GitHub auto-closed this PR when #6's base branch was deleted on merge and refuses to reopen/retarget past that. Content identical to the reviewed branch (uint64 bound included).

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.

1 participant