Skip to content

fix(release): restore governed Release Please tag identity #63

Description

@robinbraemer

Why

The normal CLI release path is blocked after chore(main): release 0.11.0 (#49) merged. The release must continue through Release Please and the existing immutable-artifact workflow; it must not be recovered by a manual tag or release.

Exact evidence

  • Repository tag ruleset 22528085, Tags via sync identity only, is active for every tag and blocks creation, updates, and deletion. Its sole bypass is RepositoryRole ID 5 (admin).
  • RELEASE_PLEASE_TOKEN is absent from akua-dev/cli, so .github/workflows/release-please.yml correctly falls back to github.token.
  • Post-merge Release Please run 34835153882 reached release creation but failed with pre_receive Repository rule violations found: Cannot create ref due to creations being restricted.
  • Adding generic GitHub Actions (integration ID 15368) as a ruleset bypass was rejected by GitHub with HTTP 422: integrations must belong to the ruleset source or owner organization. No ruleset change was made.
  • The runner outage is separately fixed by fix(ci): restore runnable CLI release automation #62: hosted release jobs ran successfully, and chore(main): release 0.11.0 #49 CI was fully green before merge.

Acceptance criteria

  • Provision or select a narrow, organization-owned GitHub App that is installed on akua-dev/cli and has only the release identity permissions needed to create the release tag/Release Please release.
  • Add that exact App integration, not a generic Actions bypass and not a human role, as the bypass actor for tag ruleset 22528085.
  • Make the App installation token available to the existing RELEASE_PLEASE_TOKEN input through the approved secret-management path; keep credentials out of source, logs, and workloads.
  • Keep the fallback to github.token for repositories/environments that do not use the governed tag ruleset.
  • Re-run the normal main-push Release Please path for the already-merged 0.11.0 release and prove it creates v0.11.0, then completes the existing immutable package, target smoke, publish, and tap-update workflow.
  • Verify the public v0.11.0 artifact contains the strict QuotaInfo lifetime contract and the operations context-header forwarding fix.

Out of scope

  • No human PAT as a release credential.
  • No manual tag, manual GitHub Release, direct artifact upload, or bypass publication.
  • No broad GitHub Actions ruleset bypass.
  • No changes to artifact integrity checks, runner policy, or unrelated workflows.

Related

Activity

  1. robinbraemer commented on Sep 14, 2026

    @robinbraemer
    MemberAuthor

    Investigation result: no safe existing release identity; brokered AgentOS identity required

    I reproduced the release failure and inspected the active repository/org state on 2026-09-14.

    Root cause and current state

    • Failed normal run 34835153882 reached release-please 17.6.0 and failed only when GitHub tried to create the release/tag: Cannot create ref due to creations being restricted.
    • Active tag ruleset 22528085 still covers ~ALL tags with creation, update, and deletion restrictions. Its only bypass actor is repository-admin role ID 5.
    • RELEASE_PLEASE_TOKEN is absent; the checked-in fallback to github.token is therefore behaving exactly as designed, but that token is not an allowed tag actor.
    • The repository has only HOMEBREW_TAP_TOKEN; there is no hidden release-App secret or variable to adopt.

    Existing App audit

    None of the installed organization Apps is an acceptable release identity:

    • akua-platform-ci (App ID 4658848) is selected-repository cnap CI infrastructure and lacks issues:write plus pull_requests:write.
    • akua-renovate (App ID 2948188) has the needed write permissions, but is installed across the organization and is deliberately a broad dependency-automation identity. Reusing it would violate the CLI-only/narrow-identity acceptance criterion.
    • akua-agentos is organization-wide and extremely privileged; it must never become a release bypass actor.
    • Third-party Apps and product Apps are not organization-owned release identities.

    Exact new GitHub App boundary

    Create one organization-owned App (suggested slug/name: akua-cli-release) with:

    • Repository permissions: Contents: Read and write, Pull requests: Read and write, Issues: Read and write; implicit Metadata: Read only.
    • Organization permissions: none.
    • Events/webhooks: none.
    • Installation: Only select repositories → exactly akua-dev/cli.
    • No Actions, Checks, Packages, Workflows, Administration, Members, Secrets, Deployments, or org-wide permission.

    contents:write is required for the release tag/GitHub Release and release-PR git objects; pull_requests:write and issues:write are required for the ordinary Release Please PR/label lifecycle. No broader permission is justified.

    GitHub App creation/installation is organization UI authority; the current admin:org user token can inspect installations but cannot create an App or mint its installation token through REST. This is the first bounded external state.

    Exact ruleset update after the App exists

    Preserve every current rule and the existing admin actor, adding only the new organization-owned App's App ID (not installation ID) as an Integration bypass actor:

    {
      "name": "Tags via sync identity only",
      "target": "tag",
      "enforcement": "active",
      "bypass_actors": [
        {
          "actor_id": 5,
          "actor_type": "RepositoryRole",
          "bypass_mode": "always"
        },
        {
          "actor_id": "<AKUA_CLI_RELEASE_APP_ID>",
          "actor_type": "Integration",
          "bypass_mode": "always"
        }
      ],
      "conditions": {
        "ref_name": {
          "exclude": [],
          "include": ["~ALL"]
        }
      },
      "rules": [
        { "type": "creation" },
        { "type": "update" },
        { "type": "deletion" }
      ]
    }

    Apply via PUT /repos/akua-dev/cli/rulesets/22528085, then read the ruleset back and verify exactly those two bypass actors and the unchanged three restrictions. Adding generic GitHub Actions integration ID 15368 remains invalid and out of scope.

    Why the standard Actions-token patch is rejected

    actions/create-github-app-token would require copying the App private key into a GitHub Actions secret and then into the hosted job. Current repository-wide security policy explicitly forbids copied App keys/PATs in CI and requires third-party credentials to remain in Access Proxy. A long-lived RELEASE_PLEASE_TOKEN, a periodically refreshed installation-token secret, and a human PAT are therefore not acceptable fixes.

    No CLI workflow patch is safe in isolation today: the existing fallback remains necessary for repositories/environments without this governed tag ruleset, while changing it to reference an unprovisioned secret merely replaces the tag-policy failure with a credential failure.

    Bounded next design: broker through AgentOS

    The smallest compliant follow-up is a dedicated AgentOS release identity, not broader release plumbing:

    1. Keep the new App private key only in the AgentOS Access Proxy encrypted credential store.
    2. Add one dynamic GitHub App installation credential down-scoped by GitHub itself to repository cli and exactly contents:write, pull_requests:write, issues:write.
    3. Add a dedicated platform-cli-release ServiceAccount/entity using a projected token with audience access-proxy; do not reuse ordinary CI or Renovate identities.
    4. Execute only the Release Please control-plane job under that identity in AgentOS and route its GitHub REST/GraphQL requests through Access Proxy, where the real App credential is injected. Enumerate and grant the exact Release Please 17.6.0 request paths before activation; no repos/akua-dev/* wildcard.
    5. Keep artifact packaging/smoke/publishing on the existing immutable workflow once release_created == true; the App is only the Release Please actor.
    6. Add the App to tag ruleset 22528085, activate the brokered job, and dispatch the normal Release Please workflow. Do not create v0.11.0 manually.

    This path needs a short design/implementation slice in cnap because the currently deployed Access Proxy is internal-only and trusts Kubernetes projected identities, while the CLI Release Please job currently runs on a GitHub-hosted runner. Restoring a copied private key in Actions would be quicker but violates the standing credential boundary, so it is intentionally not proposed.

    Terminal verification after activation

    • Normal Release Please run creates immutable v0.11.0 and the GitHub Release as the new App actor.
    • Existing reusable workflow completes package, all target-native smoke jobs, immutable asset upload/verification, and Homebrew tap dispatch.
    • v0.11.0 reports the expected version and proves the already-merged operations-context and strict quota-lifetime contracts.
    • Ruleset readback contains only admin role ID 5 plus the new CLI release App; no GitHub Actions, Renovate, human, or broad App bypass.
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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions