Skip to content

F1: Read-only Git document access

F1 adds the smallest repository-read surface needed by a continuity client. It does not copy a repository into HeyAira and it does not create a GitHub App, push code, open pull requests, or change deployment infrastructure.

Contract

The authenticated project is the tenant boundary. A local administrator first links a GitHub repository and allowlists a document at one immutable commit:

heyaira-admin add-document-source \
  --project-id <project-id> \
  --github-owner h8v6 \
  --github-repository heyaira \
  --document-role runtime \
  --path docs/CONTINUITY_PROTOCOL.md \
  --commit-sha <40-character-commit-sha>

The command stores only repository identity, role, path, commit SHA, and a fragment limit. It is an administrator operation; there is no model-facing write operation for changing the allowlist.

runtime_bootstrap_get() returns the authenticated project's active pinned references. The response contains source_id, repository identity, role, path, commit SHA, and limits. If no active runtime source exists, it returns runtime_unconfigured.

git_document_get(source_id, start_byte?, max_bytes?, cursor?) reads one allowlisted source. The server resolves the source from the authenticated project and calls the fixed GitHub Contents API host with the pinned commit SHA. The model cannot supply an arbitrary repository URL, branch, or path.

The response contains the UTF-8 content fragment, byte range, full-file SHA-256, fragment SHA-256, and an opaque next_cursor when more content is available. A cursor is signed and bound to the project, principal, source, commit, path, offset, and expiry. Each continuation re-checks authorization and re-reads GitHub; F1 has no cache.

Limits and failure behavior

  • documents:read is a separate OAuth scope; existing OAuth grants are not silently expanded.
  • Legacy static project tokens retain only their historical memory/task permissions. They do not receive documents:read; a document read needs an explicit OAuth grant containing that scope.
  • Only ordinary UTF-8 files are accepted. Directories, symlinks, gitlinks, invalid UTF-8, path traversal, and non-UTF-8 byte ranges are rejected.
  • A file is limited to 1 MB and a response fragment to 64 KB.
  • A full 40-character commit SHA is required; branch and tag names are not accepted by the F1 registry.
  • The GitHub Contents JSON response is bounded to 1,500,000 bytes before JSON parsing. This leaves room for base64 and JSON overhead around a valid 1 MB decoded file while bounding responses without or with a false Content-Length. Redirects are rejected rather than followed.
  • Provider failures are returned as stable codes such as provider_not_found, provider_forbidden, provider_unavailable, or provider_unconfigured; credentials and response bodies are never logged.

The provider follows GitHub's repository contents read contract and uses a read-only injected credential. GitHub documents the path and ref inputs and the Contents read permission in its repository contents API documentation. Installation-token acquisition is a separate future deployment concern; this local F1 only provides the adapter seam and synthetic tests.

What F1 does not claim

F1 does not provide a HeyAira state snapshot, event sourcing, background routing, thread wake-up, GitHub App installation, or public GitHub access. The tests use an injected synthetic provider and therefore are not evidence of a public GitHub deployment. Production credential wiring and external verification remain a later, explicitly authorized stage.

Local verification

.venv/bin/pytest

The document tests exercise allowlist-shaped source records, UTF-8-safe fragments, signed cursor binding, object/encoding/limit failures, and the fixed-host GitHub adapter. They do not contact GitHub and do not require a production token.

The full MCP-to-document path is covered by an opt-in integration test. Point HEYAIRA_F1_E2E_DATABASE_URL at a newly created isolated PostgreSQL database before running it; the test starts a local MCP server, inserts synthetic project/OAuth/allowlist state, uses a synthetic Git provider, verifies bootstrap and continuation, revokes the source between reads, and confirms a legacy token is denied before the provider is called:

HEYAIRA_F1_E2E_DATABASE_URL=postgresql://... \
  .venv/bin/pytest -q tests/test_f1_mcp_e2e.py