feat: manage ycst-org-uk and its admins team - #64
Conversation
Second managed org, team-based admin via _teams.yaml, and the move of the two ycst repos out of yo61. Records four mechanism findings established by experiment: moved blocks work across provider aliases and renamed for_each keys; removed blocks reject instance keys; -target scopes at the org module boundary; a cross-org moved block cannot be targeted to one side. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013AuKFF3iD2LxrFNGT5Hmih
Reword the team_ids fallback comment in modules/github-repo/main.tf: the "unmanaged team" fallback is unreachable through modules/org, which preconditions every slug against local.teams; it only survives for direct callers. Also fix the comment's claim that the dependency edge depends on a successful lookup — it doesn't, the edge comes from referencing var.team_ids at all. Guard two yamldecode/lookup null cases in modules/org/data.tf: a null `teams:` key in a repo's collaborators block, and a present-but-empty _teams.yaml, both of which previously blew up with Terraform's generic iteration error instead of the named failures these locals exist to produce. Document the _teams.yaml key/slug naming constraint in CLAUDE.md, correct the org-guard comment in Taskfile.yaml to describe what the directory check actually proves, and add an init step, a token-permission precheck, and two accuracy notes to the migration plan doc.
There was a problem hiding this comment.
Adds optional per-org team management (data//_teams.yaml -> github_team + authoritative github_team_members) and wires up the new ycst-org-uk org and its admins team, plus a task plan ORG=<org> scoping option. The team_id dependency edge, the plan-time precondition against unknown team slugs, and the org-guard/TARGET templating in the Taskfile are all consistent with each other and with the docs updated in the same PR. Checked the fallback path in modules/github-repo/main.tf (lookup(var.team_ids, slug, slug)) against the new precondition in modules/org/data.tf and confirmed it's made unreachable for org-module callers, and confirmed no existing yo61 repo YAML currently exercises the teams fallback. No Critical or Important issues found.
Adds team support to
modules/org, wires up theycst-org-ukorg, and letstask planscope to a single org. No repositories move in this PR.modules/orgreads an optionaldata/<org>/_teams.yamland creates onegithub_teamplus one authoritativegithub_team_membersper key, passing theresulting IDs into each repo so a team is created before a repo grants to it.
Passing IDs rather than slugs is what creates that dependency edge — a slug-only
map would not reference
github_teamat all. A plan-time precondition fails ona team slug no managed team provides. An org without the file manages no teams,
so
yo61's existingownersandubntteams stay unmanaged.data/ycst-org-uk/holds only_teams.yaml; the twoycst-*repos move in alater PR, after they are transferred on GitHub out of band.
task plan ORG=<org>renders-target=module.org_<org>and refuses a slug withno data directory, because an unmatched
-targetyields only a soft warning andan empty plan. Targeting skips the excluded org's drift detection, so unscoped
task planstays the default.task applyis unchanged — a saved plan filecarries its own targeting.
Planned against the live backend at 883708c before merge, both scoped to the new
org and unscoped:
3 to add, 0 to change, 0 to destroyeither way, with nounmanaged-repo warnings. The unscoped run is the one that matters — it shows
yo61's existing instances produce no diff.Design:
docs/superpowers/specs/2026-08-12-ycst-org-uk-migration-design.mdPlan:
docs/superpowers/plans/2026-08-13-ycst-org-uk-migration.md🤖 Generated with Claude Code
https://claude.ai/code/session_01C15usdmazQC71xZC1YFGHg