Require user-provisioned release credentials
Hop-State: A_06FN6KM758JV6S44F6CA6W0 Hop-Proposal: R_06FN6KJWAY5XWVMCVQHCXKR Hop-Task: T_06FN6GZKFMRV2HP5N7XMNSR Hop-Attempt: AT_06FN6GZKFP22ZCFRXGB7V00
This commit is contained in:
@@ -83,3 +83,25 @@ func TestDistributionDoesNotRequireGiteaActions(t *testing.T) {
|
|||||||
t.Fatal("release checklist still depends on a Gitea Actions workflow")
|
t.Fatal("release checklist still depends on a Gitea Actions workflow")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestReleaseWorkflowRequiresPreProvisionedCredential(t *testing.T) {
|
||||||
|
root := filepath.Clean(filepath.Join("..", ".."))
|
||||||
|
script, err := os.ReadFile(filepath.Join(root, "scripts", "release-local.sh"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !strings.Contains(string(script), "pre-existing scoped GITEA_TOKEN") {
|
||||||
|
t.Fatal("release script does not require a pre-provisioned credential")
|
||||||
|
}
|
||||||
|
if strings.Contains(string(script), "/tokens") {
|
||||||
|
t.Fatal("release script must not manage provider tokens")
|
||||||
|
}
|
||||||
|
checklist, err := os.ReadFile(filepath.Join(root, "wiki", "Release-Checklist.md"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !strings.Contains(string(checklist), "must never create, rotate, list,") ||
|
||||||
|
!strings.Contains(string(checklist), "or revoke account tokens") {
|
||||||
|
t.Fatal("release checklist does not forbid agent token management")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ done
|
|||||||
|
|
||||||
if [ "$mode" = --publish ]; then
|
if [ "$mode" = --publish ]; then
|
||||||
[ -f LICENSE ] || fail "LICENSE is required before publishing"
|
[ -f LICENSE ] || fail "LICENSE is required before publishing"
|
||||||
[ -n "${GITEA_TOKEN:-}" ] || fail "set a scoped GITEA_TOKEN in the local environment"
|
[ -n "${GITEA_TOKEN:-}" ] || fail "provide a pre-existing scoped GITEA_TOKEN through the local secret store"
|
||||||
[ -z "$(git status --porcelain)" ] || fail "the Git worktree must be clean"
|
[ -z "$(git status --porcelain)" ] || fail "the Git worktree must be clean"
|
||||||
tag=$(git describe --tags --exact-match HEAD 2>/dev/null) ||
|
tag=$(git describe --tags --exact-match HEAD 2>/dev/null) ||
|
||||||
fail "HEAD must have an exact release tag"
|
fail "HEAD must have an exact release tag"
|
||||||
|
|||||||
@@ -73,6 +73,11 @@ variable or secret-manager name instead.
|
|||||||
- Do not run `git commit`, `git checkout`, `git switch`, `git branch`,
|
- Do not run `git commit`, `git checkout`, `git switch`, `git branch`,
|
||||||
`git rebase`, `git reset`, `git stash`, `git worktree`, or `git push`.
|
`git rebase`, `git reset`, `git stash`, `git worktree`, or `git push`.
|
||||||
- Do not stage files. Hop captures every nonignored workspace change.
|
- Do not stage files. Hop captures every nonignored workspace change.
|
||||||
|
- Never create, rotate, enumerate, revoke, or paste account access tokens
|
||||||
|
through a provider website or API. For release or publishing work, use only a
|
||||||
|
credential the user has already provisioned in an OS secret store or supplied
|
||||||
|
through the runtime's secret mechanism. If it is missing, stop and ask the
|
||||||
|
user to provision it; do not call a token-management endpoint.
|
||||||
- Give a subagent project-changing work only after creating a distinct Hop
|
- Give a subagent project-changing work only after creating a distinct Hop
|
||||||
prompt/attempt for that delegation.
|
prompt/attempt for that delegation.
|
||||||
- Never discard either side of concurrent work. Let Hop perform its three-way
|
- Never discard either side of concurrent work. Let Hop perform its three-way
|
||||||
|
|||||||
@@ -158,6 +158,15 @@ sanitizer replaces detected credential values before any durable write and
|
|||||||
returns only typed redaction counts. Do not place the value in any later
|
returns only typed redaction counts. Do not place the value in any later
|
||||||
command, summary, output, or source file.
|
command, summary, output, or source file.
|
||||||
|
|
||||||
|
## Account credential boundary
|
||||||
|
|
||||||
|
Hop never creates, rotates, lists, or revokes provider access tokens. Agents
|
||||||
|
must not use account token-management APIs or settings pages as a shortcut for
|
||||||
|
publishing work. A release or publishing task may use only a pre-existing
|
||||||
|
credential the user deliberately provisioned through an OS secret store or the
|
||||||
|
runtime's secret mechanism. When that credential is absent or invalid, stop and
|
||||||
|
ask the user to replace it; never mint a task-named token.
|
||||||
|
|
||||||
## Exit codes
|
## Exit codes
|
||||||
|
|
||||||
| Code | Meaning |
|
| Code | Meaning |
|
||||||
|
|||||||
@@ -12,8 +12,11 @@ The canonical repository is `githop.xyz/GnosysLabs/Hop`.
|
|||||||
- Configure `origin` as `https://githop.xyz/GnosysLabs/Hop.git`.
|
- Configure `origin` as `https://githop.xyz/GnosysLabs/Hop.git`.
|
||||||
- Keep Gitea Actions disabled when the instance does not have dedicated runner
|
- Keep Gitea Actions disabled when the instance does not have dedicated runner
|
||||||
capacity; Hop's release process does not depend on it.
|
capacity; Hop's release process does not depend on it.
|
||||||
- Create a narrowly scoped maintainer access token that can write releases.
|
- Provision a narrowly scoped maintainer access token outside the agent session
|
||||||
Export it as `GITEA_TOKEN` only for the local publish command, then unset it.
|
and store it in the operating system's secret store. Agents and release
|
||||||
|
scripts may use that existing credential, but must never create, rotate, list,
|
||||||
|
or revoke account tokens through Gitea's website or API. Export it as
|
||||||
|
`GITEA_TOKEN` only for the local publish command, then unset it.
|
||||||
- When upgrading GoReleaser, update its pinned version and four archive
|
- When upgrading GoReleaser, update its pinned version and four archive
|
||||||
checksums in `scripts/release-local.sh` from the official checksum file.
|
checksums in `scripts/release-local.sh` from the official checksum file.
|
||||||
- Permit release attachment MIME types for `.tar.gz`, `.zip`, and `.txt` in
|
- Permit release attachment MIME types for `.tar.gz`, `.zip`, and `.txt` in
|
||||||
@@ -49,7 +52,8 @@ default skill destinations while preserving unrelated user files.
|
|||||||
injected into the binaries automatically.
|
injected into the binaries automatically.
|
||||||
2. Run `scripts/release-local.sh --snapshot` and inspect the artifacts.
|
2. Run `scripts/release-local.sh --snapshot` and inspect the artifacts.
|
||||||
3. Create a signed semantic-version tag such as `v0.1.0-alpha.1` and push it.
|
3. Create a signed semantic-version tag such as `v0.1.0-alpha.1` and push it.
|
||||||
4. Export a locally stored, scoped token: `export GITEA_TOKEN=...`.
|
4. Read a pre-provisioned, locally stored scoped token into `GITEA_TOKEN`.
|
||||||
|
Do not generate a task-specific token from an agent session.
|
||||||
5. Run `scripts/release-local.sh --publish`. It reruns race tests, vet, installer
|
5. Run `scripts/release-local.sh --publish`. It reruns race tests, vet, installer
|
||||||
checks, builds six platform archives, generates `checksums.txt`, and uploads
|
checks, builds six platform archives, generates `checksums.txt`, and uploads
|
||||||
a draft without executing build work on the Gitea server.
|
a draft without executing build work on the Gitea server.
|
||||||
|
|||||||
@@ -38,7 +38,9 @@ public key independently. Checksum signing is listed as a launch gate in the
|
|||||||
Release builds execute on a maintainer machine, not on the Gitea server. Use a
|
Release builds execute on a maintainer machine, not on the Gitea server. Use a
|
||||||
trusted, patched machine; keep the release token out of shell history and source
|
trusted, patched machine; keep the release token out of shell history and source
|
||||||
files; scope it to the Hop repository; export it only for the publish command;
|
files; scope it to the Hop repository; export it only for the publish command;
|
||||||
and unset it immediately afterward. Releases upload as drafts for review.
|
and unset it immediately afterward. Releases upload as drafts for review. The
|
||||||
|
token must be provisioned by the user outside the agent session: Hop and its
|
||||||
|
agents never create, rotate, list, or revoke provider account tokens.
|
||||||
|
|
||||||
## Filesystem safety
|
## Filesystem safety
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user