Skip to content

feat(acl): add tag:tag-authority as reconciler owner tag (TIN-2639) - #19

Merged
Jesssullivan merged 3 commits into
mainfrom
feat/tin-2639-tag-authority-owner
Jul 27, 2026
Merged

feat(acl): add tag:tag-authority as reconciler owner tag (TIN-2639)#19
Jesssullivan merged 3 commits into
mainfrom
feat/tin-2639-tag-authority-owner

Conversation

@Jesssullivan

Copy link
Copy Markdown
Owner

Why

The TIN-2639 scoped OAuth client failed its Phase-4 bounded write (HTTP 400: cannot write tag:dollhouse) because no policy-defined tag owns the tags the lab reconciler manages. The rotation runbook's Tag Authority Gate prescribes exactly this: "grant the exact final tag set, or a policy-defined owner tag that owns that complete set" — after reconciling inventory to live (the lab desired-tags trim PR, in flight under the same 2026-07-27 ruling).

What

  • constants.dhall: define tag_authority = "tag:tag-authority"
  • fragments/core.dhall: admin-owned tagOwners entry for it, plus ownership of the exact 14-tag union the reconciler can write post-trim (dollhouse, dev, k8s, k8s-operator, qa, rj-gateway, services, setec, staging, tsidp, subnet-router, switch, tinyland-lab-moonlight, tinyland-lab-sunshine — read live 2026-07-27)

just check + just build pass; rendered policy verified: 14 tagOwners entries carry tag:tag-authority.

Merge semantics + ceremony

Merging auto-applies the policy via cd.yml (the repo's reviewed flow). Then the attended ceremony: re-mint the OAuth client with tag:tag-authority (client tags are fixed at creation) → Phase-3 strict proof → one idempotent bumble write ([dollhouse][dollhouse]) with audit-log verification → Phase-5 revoke of the legacy tskey-api-* before 2026-07-31. Stop line: if the write isn't green by 07-30 EOD, extend the legacy token instead — never revoke first.

The TIN-2639 scoped OAuth client failed its Phase-4 bounded write
(HTTP 400: cannot write tag:dollhouse) because no policy-defined tag
owns the tags the lab reconciler manages. Per the rotation runbook's
tag-authority gate, define tag:tag-authority (admin-owned) and grant it
ownership of the exact 14-tag union the reconciler can write after the
2026-07-27 inventory-to-live trim: dollhouse, dev, k8s, k8s-operator,
qa, rj-gateway, services, setec, staging, tsidp, subnet-router, switch,
tinyland-lab-moonlight, tinyland-lab-sunshine.

Ceremony follow-up (operator): re-mint the OAuth client with
tag:tag-authority (client tags are fixed at creation), re-run Phase-3
proof, one idempotent bumble write ([dollhouse] -> [dollhouse]) with
audit-log verification, then Phase-5 revoke of the legacy tskey-api-*
before 2026-07-31.
@github-actions

Copy link
Copy Markdown

⚠️ ACL Validation

Validation

tailnet-acl dev shell
  dhall:         1.42.3
  dhall-to-json: 1.7.12
  just:          just 1.46.0
Loading local policy from /home/runner/work/tailnet-acl/tailnet-acl/generated/policy.json ...
Fetching live ACL from taila4c78d.ts.net ...

Validation FAILED: local policy differs from live.
acls: OK
autoApprovers: OK
grants: OK
groups: OK
hosts: OK
nodeAttrs: OK
ssh: OK
tagOwners: MISMATCH
  key 'tag:dev':
    live:  ["autogroup:admin", "group:developers"]
    local: ["tag:tag-authority", "autogroup:admin", "group:developers"]
  key 'tag:dollhouse':
    live:  ["autogroup:admin", "group:dollhouse-admins"]
    local: ["tag:tag-authority", "autogroup:admin", "group:dollhouse-admins"]
  key 'tag:k8s':
    live:  ["tag:k8s-operator", "autogroup:admin", "group:dollhouse-admins"]
    local: ["tag:tag-authority", "tag:k8s-operator", "autogroup:admin", "group:dollhouse-admins"]
  key 'tag:k8s-operator':
    live:  ["tag:k8s-operator", "autogroup:admin", "group:dollhouse-admins"]
    local: ["tag:tag-authority", "tag:k8s-operator", "autogroup:admin", "group:dollhouse-admins"]
  key 'tag:qa':
    live:  ["autogroup:admin", "group:developers"]
    local: ["tag:tag-authority", "autogroup:admin", "group:developers"]
  key 'tag:rj-gateway':
    live:  ["autogroup:admin", "group:dollhouse-admins"]
    local: ["tag:tag-authority", "autogroup:admin", "group:dollhouse-admins"]
  key 'tag:services':
    live:  ["autogroup:admin", "group:dollhouse-admins"]
    local: ["tag:tag-authority", "autogroup:admin", "group:dollhouse-admins"]
  key 'tag:setec':
    live:  ["autogroup:admin", "group:dollhouse-admins"]
    local: ["tag:tag-authority", "autogroup:admin", "group:dollhouse-admins"]
  key 'tag:staging':
    live:  ["autogroup:admin", "group:developers"]
    local: ["tag:tag-authority", "autogroup:admin", "group:developers"]
  key 'tag:subnet-router':
    live:  ["autogroup:admin", "group:dollhouse-admins"]
    local: ["tag:tag-authority", "autogroup:admin", "group:dollhouse-admins"]
  key 'tag:switch':
    live:  ["autogroup:admin", "group:dollhouse-admins"]
    local: ["tag:tag-authority", "autogroup:admin", "group:dollhouse-admins"]
  key 'tag:tag-authority': ONLY IN LOCAL
  key 'tag:tinyland-lab-moonlight':
    live:  ["autogroup:admin", "group:dollhouse-admins"]
    local: ["tag:tag-authority", "autogroup:admin", "group:dollhouse-admins"]
  key 'tag:tinyland-lab-sunshine':
    live:  ["autogroup:admin", "group:dollhouse-admins"]
    local: ["tag:tag-authority", "autogroup:admin", "group:dollhouse-admins"]
  key 'tag:tsidp':
    live:  ["autogroup:admin", "group:dollhouse-admins"]
    local: ["tag:tag-authority", "autogroup:admin", "group:dollhouse-admins"]

Diff against live

tailnet-acl dev shell
  dhall:         1.42.3
  dhall-to-json: 1.7.12
  just:          just 1.46.0
Fetching live ACL ...

Changes to apply:
  ~ tagOwners: changed

(dry run, no changes made)

@Jesssullivan
Jesssullivan merged commit a44dc90 into main Jul 27, 2026
3 checks passed
@Jesssullivan
Jesssullivan deleted the feat/tin-2639-tag-authority-owner branch July 27, 2026 22:33
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