0e2cc048ec
2 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
b1c976a54d
|
fix(github): refresh installation token when TTL < 10 min (#547) (#567)
Root cause: the github-app-auth plugin injects GH_TOKEN + GITHUB_TOKEN
into each workspace container's env at provision time (EnvMutator). Those
are GitHub App installation tokens with a fixed ~60 min TTL. The plugin
has an in-process cache that proactively refreshes 5 min before expiry —
but the workspace env is set once at container start and never updated.
Any workspace alive >60 min ends up with an expired token.
Fix (Option B — on-demand endpoint):
pkg/provisionhook:
- Add TokenProvider interface: Token(ctx) (token, expiresAt, error)
Lives in pkg/ (public) so the github-app-auth plugin can implement it.
- Add Registry.FirstTokenProvider() — discovers the first mutator that
also satisfies TokenProvider via interface assertion. Safe under
concurrent reads (existing RWMutex).
platform/internal/handlers/github_token.go:
- New GitHubTokenHandler serving GET /admin/github-installation-token
- Delegates to the registered TokenProvider (plugin cache — always fresh)
- 404 if no GitHub App configured, 500 + [github] prefix log on error
- Never logs the token itself
platform/internal/handlers/workspace.go:
- Add TokenRegistry() getter so the router can wire the handler without
coupling to WorkspaceHandler internals
platform/internal/router/router.go:
- Register GET /admin/github-installation-token under AdminAuth
workspace-template/:
- scripts/molecule-git-token-helper.sh — git credential helper; calls
the platform endpoint on every push/fetch; falls through to next
helper (operator PAT) if platform unreachable
- entrypoint.sh — configure the credential helper at startup
Why Option B over Option A (background goroutine):
- The plugin already has its own cache refresh; nothing to refresh here.
- Pushing env updates into running containers requires docker exec, which
the architecture explicitly rejects (issue #547 "Alternatives").
- Pull-based is stateless, trivially testable, zero extra goroutines.
Closes #547
Co-authored-by: Molecule AI DevOps Engineer <devops-engineer@agents.moleculesai.app>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
|
||
|
|
067a8333ce |
feat(workspace): gh-wrapper — auto-tag agent PRs + issues with role
Every agent in the template currently uses the same GitHub PAT, so \`gh pr list\` shows every PR as authored by the CEO's account with no signal which agent opened each one. Commits already carry per-agent authors (GIT_AUTHOR_NAME from #402). This wrapper extends the identity split to the PR/issue metadata surface layer that commit attribution can't reach. ## How it works A tiny bash script installed at \`/usr/local/bin/gh\`, which sits earlier in PATH than the real binary at \`/usr/bin/gh\`. For \`gh pr create\` and \`gh issue create\`: - Title gets prefixed with \`[Role Name]\` — e.g. \`[Frontend Engineer] fix: canvas grid index\` - Body gets \`\n\n---\n_Opened by: Molecule AI <Role>_\` appended Role is read from \`GIT_AUTHOR_NAME\` which the platform provisioner sets to \`Molecule AI <Role>\` (shipped with #402). Accepts both \`--title X\` and \`--title=X\` forms. Same for \`--body\`. Anything that isn't \`gh pr create\` or \`gh issue create\` (e.g. \`gh pr list\`, \`gh issue view\`, \`gh run watch\`) passes through untouched. No behaviour change for read-side operations. ## Idempotent - If the title already starts with \`[...]\` the wrapper does not re-prefix. \`gh pr edit\` flows that resubmit title won't layer multiple tags. - If the body already contains \`Opened by: Molecule AI\` the footer is not re-appended. ## Fail-open When \`GIT_AUTHOR_NAME\` is absent or doesn't start with \`Molecule AI \`, the wrapper exec's the real gh with unchanged args. No call is ever blocked by this script. ## Test coverage \`tests/test_gh_wrapper.sh\` — 12 cases, no network, no Docker: - Passthrough for non-create subcommands (pr list) - pr create title prefix + body footer - issue create with \`--title=X\` \`--body=X\` equals-form - Idempotent title re-prefix - Idempotent body footer (count = 1 after two applies) - Missing GIT_AUTHOR_NAME → passthrough, title preserved - Malformed GIT_AUTHOR_NAME (not "Molecule AI ...") → passthrough All 12 pass. Test script is standalone bash + a temp fake gh binary that echoes argv; safe to run in CI's Python Lint & Test job via subprocess shell-out. ## Deployment note This lands in the workspace image. Existing containers keep their old /usr/bin/gh until the image is rebuilt and they're re-provisioned (POST /workspaces/:id/restart {}). No migration required; the wrapper just starts tagging PRs once the new image is rolled. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |