Gatehouse
by ethanl05
README.md
<p align="center">
<img src="assets/gatehouse-icon.png" alt="Gatehouse icon" width="180">
</p>
<h1 align="center">Gatehouse</h1>
<p align="center"><strong>Let your coding agent ship without ever seeing your password.</strong></p>
<p align="center">
<a href="README.md">English</a> ·
<a href="README.zh-CN.md">简体中文</a> ·
<a href="README.ja.md">日本語</a> ·
<a href="README.es.md">Español</a>
</p>
Gatehouse is the local trust layer between an AI coding agent and the accounts
that get software released. The agent asks for a named capability. Your Mac
holds the credential, your policy decides the scope, and you get the final say
when an action matters.
**Faster releases. Fewer login interruptions. No secrets in the model.**
[](.github/workflows/ci.yml)
[](LICENSE)
[](docs/architecture.md)
Gatehouse is a companion to Codex, not a modification of Codex. Its first
integration is a stdio MCP server, so it can be added alongside Codex's own
browser and native-host components.
## Why Gatehouse
AI coding agents are already good at preparing a release. The fragile part is
the last mile: a browser asks for a password, a deployment CLI needs a token,
or a production action needs a human reviewer. Copying credentials into chat,
shell history, screenshots, or repository files creates the wrong kind of
automation.
Gatehouse turns that last mile into a small, inspectable protocol:
| Agent asks for | Gatehouse returns |
| --- | --- |
| A registered site login | An origin-bound status |
| A named release workflow | A redacted verification receipt |
| A rollback for a known run | A local approval decision and outcome |
The agent never receives a password, cookie, API token, OTP, or private key.
## What it does
- Stores only credential references in project configuration; secret material
stays in the operating system's credential store.
- Requires a site profile and exact origin match before a browser login.
- Supports ordinary username/password fill-and-submit after a user-approved
capability grant.
- Pauses for MFA, CAPTCHA, WebAuthn/security keys, payments, and destructive
actions.
- Exposes registered workflows rather than arbitrary shell execution.
- Produces redacted, structured receipts for local, remote, public, and
business verification layers.
- Runs locally by default. A future self-hosted collaboration transport is an
optional protocol boundary, not a hosted secret vault.
## Built for the real release loop
```text
prepare → user approval → execute → poll → verify → receipt → rollback
```
The first adapters cover GitHub Actions environments, Vercel, and Tencent TAT.
They keep local commit/artifact evidence, remote invocation state, public health,
business acceptance, and rollback references separate. “Command submitted” is
not reported as “production verified.”
## Safety by default
- Default policy is deny.
- Sites must be explicitly registered with exact origins and login paths.
- Capabilities are opaque, short-lived, single-use, and scope-bound.
- MFA, CAPTCHA, WebAuthn, payments, and destructive actions stop for a human.
- Provider commands are operator-registered absolute executables with
`shell:false`; the model cannot supply a shell string.
- CI uses fake providers and no real credentials.
Gatehouse does not bypass authentication or weaken provider-side protection. It
removes secret handling from the model context while preserving the approval
boundary around sensitive actions.
## Quick start
This repository has no runtime dependencies.
```sh
npm test
npm run validate
npm run demo
```
The demo uses an in-memory credential resolver and dry-run provider adapters.
It never contacts a real provider and never needs a real secret.
## Registering with Codex
After installing this repository locally, add a separate MCP entry to your
Codex configuration. Keep the existing OpenAI browser/native-host entries
unchanged:
```toml
[mcp_servers.gatehouse]
command = "/absolute/path/to/gatehouse/src/mcp/stdio-server.mjs"
args = ["--embedded", "--config", "/absolute/path/to/gatehouse/config"]
startup_timeout_sec = 10
```
The MCP server only returns non-sensitive JSON. It does not expose a password
getter, cookie exporter, or arbitrary command runner.
## Configuration
Copy the example files into a private local configuration directory. The
example profiles are intentionally localhost-only:
```sh
mkdir -p .gatehouse/config
cp config/sites.example.json .gatehouse/config/sites.json
cp config/policy.example.json .gatehouse/config/policy.json
cp config/workflows.example.json .gatehouse/config/workflows.json
cp config/commands.local.example.json .gatehouse/config/commands.local.json
cp config/credentials.local.example.json .gatehouse/config/credentials.local.json
```
For real sites, use the enrollment workflow in the forthcoming Chrome helper
UI to confirm the origin and selectors. Do not commit local configuration or
credentials.
To exercise the local fixture, keep `npm run fixture` running, load the
`chrome-extension/` directory as an unpacked extension, and generate its
allowlist from the site profiles:
```sh
npm run generate-manifest -- --sites .gatehouse/config/sites.json
# review the generated allowlist, then use it as the extension manifest
cp chrome-extension/generated-manifest.json chrome-extension/manifest.json
```
After Chrome shows the unpacked extension ID, install the native-host manifest
with the explicit ID. This writes only the user-level Chrome registration and
an ignored project-local launcher:
```sh
npm run install-native-host -- --extension-id aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa --config "$PWD/.gatehouse/config"
```
The placeholder ID above is illustrative; use the actual lowercase extension
ID reported by Chrome.
For live provider execution, replace the three placeholder executable paths in
`commands.local.json` with absolute paths to operator-owned `gh`, `vercel`, and
Tencent CLI wrappers. The daemon may inherit an already authenticated local CLI
session or protected environment from its launch context, but the MCP input is
never allowed to carry a token. Leave the file absent to keep the adapters in
dry-run/unconfigured mode.
Run the daemon and point the MCP server at its matching per-user socket:
```sh
node src/cli.mjs serve --config "$PWD/.gatehouse/config"
node src/mcp/stdio-server.mjs --socket "/tmp/gatehouse-$(id -u).sock" --config "$PWD/.gatehouse/config"
```
Use `--live` only after reviewing the registered commands and the local
provider permissions. GitHub production environments and required reviewers,
Vercel production aliases, and Tencent TAT preflight/health checks remain
provider-side responsibilities; Gatehouse records what it actually observes.
## Security boundary
Gatehouse is not intended to bypass authentication controls. The model can
request a registered action; a local user or policy must grant it. Strong
authentication and high-impact operations remain human-gated. See
[`SECURITY.md`](SECURITY.md) for the threat model and disclosure process.
## Who it is for
Gatehouse is for solo builders, small teams, and platform engineers who want
their coding agent to prepare and release more of the work without turning
credentials into prompt data. It is intentionally local-first: start on one
Mac, review every boundary, then decide whether a future self-hosted team
transport is worth adding.
## Roadmap
- [x] Local daemon, MCP protocol, capability and approval boundary
- [x] macOS Keychain and Chrome Native Messaging bridge
- [x] GitHub/Vercel/Tencent dry-run adapters and layered receipts
- [x] Fake login fixture and secret-redaction test suite
- [ ] Interactive site enrollment UI
- [ ] Provider-specific live polling and formal-domain health adapters
- [ ] Optional self-hosted collaboration transport with independent grants
Contributions that make the boundary smaller, clearer, and easier to verify
are especially welcome. Start with [`CONTRIBUTING.md`](CONTRIBUTING.md).
## License
Apache-2.0. See [`LICENSE`](LICENSE).
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues