Generated Connect API
This portable contract describes its linked source snapshot. For current deployment instructions, use current installation, authentication and native Cloudflare guides. Historical receipts do not verify later builds.
Golf's existing session, audit, repository, organization, Git access, API credential and capability operations use the versioned golf.v1 Protobuf contract. The browser uses generated TypeScript descriptors with Connect-Web; the CLI uses generated Go clients. The local MCP adapter reuses those Go clients for 21 existing reads and adds no Connect procedures. Earlier application REST endpoints have been removed. This is a development API, with no stable public release or compatibility promise yet.
The product's api/golf/v1/golf.proto defines the API contract. See ADR 0002 for the adoption decision.
Reviewed against product commit b36d9b7. Coverage includes scoped agent usage configuration, native model catalogs and non-executing task preview. It also covers personal and named instance Codex, Claude Code and OpenCode authentication, explicit use ACLs and connection activity, all separate from execution, plus the separate Codex operator runtime foundation.
Coverage also includes the qualified local schema021/RustFS encrypted recovery and retained development push-demo increment. The push-demo increment leaves the API schema unchanged. Execution coverage includes additive manual/push run origins, the opt-in automatic branch-push materializer with grant-bound worker fences, encrypted personal repository automation grants, independent default-deny push policy, bounded static push-trigger compilation and durable execution policies/manual pipeline runs. The provider-neutral status foundation and receipt-only native push hook are included; the hook uses separate HTTP transport.
Account and administration coverage includes own public profile editing, password-confirmed self password/login-alias changes, ordinary account enrollment/reset/enable/disable, password-confirmed ordinary local-account disabling, administrator inventory and organization creation ceilings. It also includes versioned encrypted infrastructure profiles/object activation, ordinary team membership administration, personal repository collaborator access, pinned workflow inspection, bounded repository general settings and own-account SSH key management.
Other covered operations are issue discussions, owner-issued read-only API credentials, durable own-account repository creation/inspection, exact-object commit diffs, session activity, pull-request/native-review browsing and organization/team reads. This is implemented development behavior, not a released API guarantee.
The reviewed schema SHA-256 is 33dab56b4e3caaeb6c34d469599df5f238f4365bcd01bc477a95879b3c07511e. Product generation uses Buf 1.73.0, protoc-gen-go 1.36.12, protoc-gen-connect-go 1.21.0 and protoc-gen-es 2.16.0, pinned in its tools/module and web manifests. The agent-readable docs export is regenerated from the Markdown source and identifies its own content digest.
Current identity, policy and execution increments
These additional procedures use the same generated browser transport. They require current cookie-bound authority; read-only API delegations and local CLI/MCP do not acquire these new management/execution methods. IDs, credential versions, revisions and uint64 values must remain strings through Connect JSON rather than JavaScript numbers.
| Service | Methods | Bound behavior |
|---|---|---|
ProfileService | GetProfile, UpdateProfile | Own public name/bio/location/website only; immutable userId, original expectedRevision, optional present fields permit clearing. Login and email are excluded. Single native write with readback; not atomic native CAS. |
AccountSecurityService | GetAccountSecurity | Actual own Golf account ID, immutable user ID, username, unverified login alias, credential version and management eligibility. |
AccountSecurityService | ChangeOwnPassword, ChangeOwnLoginEmail | Original account/user/version plus current passwordConfirmation and proposed newPassword or loginEmail. Success returns incremented version, revoked-session count, actor operation ID and requiresLogin; all bound local sessions are revoked and current cookie expired. |
InstanceAdminService | EnrollRegularLocalAccount | Existing identity expectedNativeUserId, private forgeToken, Golf username, optional email, new password and actor passwordConfirmation. Ordinary role only; no native provisioning. |
InstanceAdminService | ResetRegularLocalPassword, EnableRegularLocalAccount | Target account/original version, new password and administrator password confirmation. Enable additionally verifies a fresh private credential matching the original identity. Reset preserves disabled state; administrator/self targets are protected. |
CodexAccountService | ListCodexConnections | instanceAdmin selects administrator management inventory; otherwise returns own personal and explicitly permitted instance metadata. No credential/challenge/ACL disclosure to use-only users. |
CodexAccountService | CreateCodexConnection, SetCodexConnectionAccess | Immutable harness/provider selectors choose Codex/OpenAI, Claude Code/Anthropic or OpenCode/Zen, Go, Anthropic or OpenAI. Named instance creation and shared access management require an enrolled local-password administrator. Personal owners may rename an existing connection with an empty allowed-user list. Updates bind connectionId, original expectedVersion, name and immutable allowedUserIds. Management does not grant use. |
CodexAccountService | GetCodexConnection | Optional connectionId selects an authorized connection; omitted ID selects the caller's personal harness/provider pair (defaults Codex/OpenAI) and returns connection state/version, auth method, reported email/plan, last check, model-verification state and management-only pending challenge when present. Personal management uses password/OAuth browser sessions; instance management requires the enrolled local administrator boundary. |
CodexAccountService | StartCodexLogin | Optional connectionId, original expectedVersion, optional immutable harness/provider selectors, enum method (CHATGPT_DEVICE/API_KEY/BROWSER_CODE) and private apiKey only for API login; receipt returns connection/challenge, never credentials. No task execution. |
CodexAccountService | CompleteAgentLogin | Exact connectionId, original expectedVersion, loginId and private authorizationCode; Claude native browser-code completion only. Code is never returned/stored; native completion and account read establish success. |
CodexAccountService | CancelCodexLogin | Optional connectionId, exact loginId and original expectedVersion; cancels only that current pending login. |
CodexAccountService | RefreshCodexConnection, DisconnectCodexConnection | Optional connectionId, original expectedVersion; native provider state refresh or confirmed Golf cache removal. No provider account/key revocation or inference claim. |
AgentUsageService | GetAgentUsage, SaveAgentUsage | Personal/instance/organization/repository settings, derived immutable scope/owner, original scope ID/config revision/authority revision, current session and account-use/catalog validation. Instructions, model/variant, triggers, model allowlists, budgets and overrides are saved configuration; no task is queued. |
AgentUsageService | ListAgentModels | Authorized connected/use-permitted connection, optional refresh. Authentication managers refresh native catalogs; shared use-only users read current sanitized cached catalogs. Codex/OpenCode native catalogs; Claude documented aliases. accessVerified stays false. |
AgentUsageService | PreviewAgentTask | Scope plus candidate account/model/variant/instructions/trigger and optional bounded limits. Resolves all higher ceilings, preserves zero spend and instructions, validates current account/catalog, never mutates configuration or dispatches. executionAvailable is false. |
ExecutionPolicyService | GetExecutionPolicy, UpdateExecutionPolicy | Instance/organization/repository ceilings, disabled/all/selected mode, immutable selected repository IDs, independent manualAllowed/pushAllowed eligibility and exact workflow paths. Push permission defaults false and does not dispatch an automatic run. Saves bind scope ID, original policy revision and native authority revision. |
AutomationGrantService | ListAutomationGrants | Repository plus optional live UUID keyset afterId; current owner/admin cookie authority, up to 25 masked grants and nextAfterId. No credential projection. |
AutomationGrantService | CreateAutomationGrant | Repository, immutable expected repository/owner IDs, explicit independent nativeToken, exact branches/workflow paths, RFC3339 expiry and canonical UUIDv4 idempotencyKey. Encrypted personal delegation; executionState is unavailable with admission disabled or requires_push_admission when enabled. Neither is an execution receipt. |
AutomationGrantService | RevokeAutomationGrant | Repository, immutable grant ID and original expectedRevision; atomically advances lifecycle/revocation epoch and actor history. Does not revoke the provider token. |
WorkflowRunService | DispatchWorkflow | Repository, exact ref, workflow path and UUID idempotency key; current write permission, supported compiler catalog, source hash and all policy ceilings required. |
WorkflowRunService | GetWorkflowRun, ListWorkflowRuns, GetWorkflowRunLogs | Current repository reads bound to recorded immutable IDs; bounded run pages and ordered logs after sequence. Historical success grants no access. |
WorkflowRunService | CancelWorkflowRun | Run ID and original status version; current qualified writer can request cancellation, fencing lease/result publication. |
OrganizationCreationService | GetOrganizationCreationPolicy, UpdateOrganizationCreationPolicy, CreateOrganization | Golf-only administrator/selected-user/all-user ceiling; version-bound policy edits and caller-native API creation. Independent native APIs retain separate authority. |
InfrastructureConnectionService | ListInfrastructureConnections | Paginated masked current profile metadata, exact active ID/version/revision plus secretless historical activeConnection metadata and separate redacted deployment defaults. |
InfrastructureConnectionService | SaveInfrastructureConnection, TestInfrastructureConnection | Current local administrator plus password step-up; immutable profile versions, optional encrypted credentials/explicit retention and original head-version checks. Tests do not switch live databases. |
InfrastructureConnectionService | ActivateInfrastructureConnection | Object-storage-only controlled write/read qualification and original profile/active revision checks. Existing sources retain immutable provider/profile/version bindings. Database activation remains unavailable. |
There is no automatic resend after an unconfirmed mutation. Local credential changes are transactional; external native profile/access writes still have bounded preflight/readback races. See settings, manual pipelines, automation grants and infrastructure for user flows and qualification limits. Worker transport is separate from browser RPC and uses scoped registration/lease capabilities; it does not accept arbitrary browser execution tokens.
WorkflowRun now has additive origin metadata: WorkflowRunOrigin distinguishes UNSPECIFIED, MANUAL and PUSH; Connect JSON fields origin, eventRef, repositoryEventId and automationGrantId identify the admitted source. Manual dispatch remains the browser operation; accepting these response fields is not an API for synthesizing a push run. See automatic push pipelines for admission boundaries. These identifiers do not bypass current repository read authority or make a result protected-merge evidence.
CodexConnectionState distinguishes UNCONFIGURED, AWAITING_AUTH, CONNECTED, REAUTH_REQUIRED and UNAVAILABLE; initial version is "0". CodexLoginMethod distinguishes ChatGPT device, API-key and Claude browser-code login. Connection metadata adds immutable harness and provider; selectors are validated against the supported catalog. OpenCode is API-key-only for Zen, Go, Anthropic and OpenAI. Connection replies include authMethod, email, planType, checkedAt, modelVerified, loginId, verificationUrl, userCode, loginExpiresAt and reasonCode. Poll GetCodexConnection while awaiting authorization; pending challenge fields are not credentials to persist or publish. Current authentication does not imply model access or task readiness. loginExpiresAt is Golf's bounded approval deadline, not provider token expiry. Additive AuditAction values 6–10 are CODEX_LOGIN_STARTED, CODEX_LOGIN_COMPLETED, CODEX_LOGIN_CANCELED, CODEX_CONNECTION_REFRESHED and CODEX_CONNECTION_DISCONNECTED; they expose no credentials/challenge and do not establish successful inference. Additive fields id, name, scope (PERSONAL/INSTANCE), canManage, canUse and management-only allowedUserIds distinguish connection authority. Audit values 11–12 record CODEX_CONNECTION_CREATED and CODEX_ACCESS_CHANGED, without secrets or approval codes. Existing personal reads remain compatible with an omitted connection ID. See coding-agent accounts.
Transport and sessions
Every application procedure uses POST /rpc/golf.v1.<Service>/<Method>. Connect JSON requests send Content-Type: application/json, Connect-Protocol-Version: 1 and the exact configured Origin. Generated clients handle protocol serialization and headers. Browser calls use same-origin cookies; never put a Forgejo token in a URL.
Repository operations require the current user's Golf session and check that user's upstream permission on each call. Responses use Cache-Control: no-store. The browser cancels and clears private queries when the session expires or the user signs out. Source, commit-diff, issue, pull-request and review panels hide previous content when a permission or resource check fails.
The OAuth callback is ordinary HTTP GET /auth/forgejo/callback, with single-use state/browser binding and PKCE rather than the RPC Origin check. It redirects to a fixed Golf page without exposing tokens or provider errors. See sign-in.
Native POST /hooks/gitea/{connectionId} intake is separate ordinary HTTP authenticated by raw-body HMAC and explicit immutable operator bindings, not a browser RPC or automation grant. See webhooks.
Health endpoints remain ordinary HTTP: GET /healthz checks process liveness and GET /readyz checks dependency readiness.
Procedures
Use the named service with the transport prefix above. A repository key is {owner, name} inside the request's repository field.
| Service | Method | Request and behavior |
|---|---|---|
SessionService | GetAuthenticationOptions | {} returns localPasswordEnabled, giteaOauthEnabled, provider label and requested scopes; unavailable/unconfigured providers are not offered as working login |
SessionService | BeginGiteaOAuth | {} sets the browser-binding cookie and returns authorizationUrl; navigate to the configured provider, then its fixed callback establishes the session |
SessionService | LoginWithPassword | {username, password} accepts an enrolled email or username in username, verifies an operator-enrolled Golf password, binds a persistent opaque session to the current immutable forge identity/account version, and returns the user with its verified local instance role |
SessionService | LoginWithGiteaToken | {token} validates the user's Forgejo credential and establishes a Golf session |
SessionService | GetSession | {} returns the current user or unauthenticated |
SessionService | ListSessions | Optional page returns active session metadata for the current immutable user and configured forge |
SessionService | RevokeSession | {sessionId} revokes an accessible active Golf session; returns currentSessionRevoked and clears the cookie when the caller revokes itself |
SessionService | RevokeOtherSessions | {} revokes all other active Golf sessions for the account, preserves the caller and returns revokedCount |
SessionService | Logout | {} invalidates the session |
ApiCredentialService | CreateApiCredential | {label, lifetimeSeconds} creates an owner/source-session-bound read-only credential; token returned once; requested lifetime is capped by source expiry |
ApiCredentialService | ListApiCredentials | Optional page returns masked metadata and currentSourceExpiresAt, never credential secrets |
ApiCredentialService | RevokeApiCredential | {credentialId} revokes an owned credential; immutable metadata/history remain |
GitAccessService | ListSSHKeys | Optional page returns the caller's native account public keys and continuation; browser session only |
GitAccessService | AddSSHKey | {title, publicKey} validates one public authentication key, adds it using the caller's native credential and verifies an owned receipt; browser session only |
GitAccessService | DeleteSSHKey | {keyId} verifies immutable ownership, removes the native key and confirms absence; browser session only |
AuditService | ListAuditEvents | Optional limit, beforeId and snapshotId return the current account’s recorded session events and stable continuation cursors |
CapabilityService | ListCapabilities | {} reports current capability states, including dependency-qualified READY or DEGRADED |
RepositoryService | ListRepositories | Optional page returns a page of repositories accessible to the user |
RepositoryService | CreateRepository | name, optional description, explicitly present private and optional idempotencyKey reserve a durable own-account create intent; inspect the returned creation.state |
RepositoryService | GetRepositoryCreation | {idempotencyKey} returns the caller's recorded intent and, when freshly authorized and ID-bound, current repository metadata |
RepositoryService | GetRepository | Repository key returns metadata, empty state and clone URLs |
RepositoryService | ListBranches | Repository key and optional page return names, commit IDs and upstream protection metadata |
RepositoryService | ListCommits | Repository key and optional ref/page return commit history |
RepositoryService | GetCommitDiff | Repository key and exact lowercase commitId return commit/parent/base metadata, bounded native rawDiff and numeric byteSize |
RepositoryService | GetContents | Repository key and optional ref/path return an immutable source snapshot and bounded preview |
RepositoryService | ListIssues | Repository key and optional enum state/page return issues, excluding pull requests |
RepositoryService | GetIssue | Repository key and positive issue number return the plain-text body and metadata; PR numbers are rejected |
RepositoryService | ListIssueComments | Repository key/expected repository ID, issue number/expected issue ID and page return one filtered native repository-wide page; empty pages may advance |
RepositoryService | CreateIssue | Repository key/expected ID, title/body and required canonical UUID key reserve one browser-session-only native issue intent |
RepositoryService | CreateIssueComment | Repository key/expected ID, issue number/expected ID, body and required UUID key reserve one browser-session-only native comment intent |
RepositoryService | GetIssueMutation | UUID key returns own historical mutation evidence and optional freshly authorized exact-ID-bound current objects; never dispatches |
RepositoryService | ListPullRequests | Repository key and optional enum state/page return native proposals with retained head snapshots |
RepositoryService | GetPullRequest | Repository key and canonical positive number return one native proposal, plain-text body and observed base/head metadata |
RepositoryService | ListPullRequestReviews | Repository key, number and optional page return provider-visible native review records |
OrganizationService | ListOrganizations | Optional page returns the current user's organization memberships |
OrganizationService | GetOrganization | {organization} returns metadata after checking actual membership |
OrganizationService | ListTeams | organization and optional page return provider-visible teams |
OrganizationService | GetTeam | {organization, teamId} returns a visible team bound to that organization |
OrganizationService | ListTeamMembers | organization, teamId and optional page return visible team members |
OrganizationService | ListTeamRepositories | organization, teamId and optional page return accessible assigned repositories |
Branch protection metadata is an upstream observation, not evidence that Golf's future merge policy has been implemented. Issue/comment creation is implemented; issue lifecycle changes, review mutations and merges remain planned. Read-only native review records are available.
Organization team membership administration
The four OrganizationAdminService procedures require a live browser session and exact Origin; delegated read-only credentials are denied. GetTeamAdministration accepts organization and teamId, returning organizationId, team, canManageMembers, revision and isOwnerTeam. Current organization members can inspect; only native organization owners can mutate non-owner teams. Golf instance administration and native site administration do not substitute for membership/ownership. Owner teams and owner-valued unit grants are locked.
ResolveTeamMember accepts organization, organizationId, teamId, userLogin and expectedRevision; it returns the exact existing user and isMember for review. AddTeamMember and RemoveTeamMember add immutable userId to those fields, returning verified user and isMember. Stale grants, mismatched identities/organization binding, adding an existing member or removing an absent member fail precondition before dispatch. The backend rechecks native owner and local session authority, sends one PUT/DELETE and separately verifies membership.
Revisions fingerprint observed organization/team metadata and grants; they do not snapshot every repository assignment or other additive grant. Username-based native operations can race independent native writes; this is not atomic CAS. A failed response may follow a completed write; refresh/inspect rather than retry automatically. Removal of one team grant is not complete access revocation. No invitations, team creation/grant editing, owner-team changes, durable membership mutation journal or custom Golf roles are introduced. See settings and the contract.
Golf instance account inventory
InstanceAdminService.ListLocalAccounts accepts the standard page request and returns accounts plus page.nextPage. Only a current explicitly enrolled Golf local password session with instance-admin authority can read it. PAT/OAuth sessions and delegated credentials cannot acquire that role, even for the same native identity. Native identity and local version/expiry/disable/session authority are rechecked around the database read and before successful encoding.
Metadata includes opaque string id, enrolled username/email, nativeUserId, golfUserId, isInstanceAdmin, disabled, string credentialVersion, createdAt and optional disabledAt. There is no inferred updated timestamp. Password hashes, encrypted provider credentials, key labels/bindings and session authenticators are excluded by SQL projection. Rows are scoped to the configured forge, ordered by immutable local-account ID; pagination is a current observation rather than a stable export snapshot.
DisableLocalAccount accepts immutable accountId, string expectedCredentialVersion and the caller's passwordConfirmation; it returns verified account, uint64 sessionsRevoked and operationId. The current local-password instance administrator must confirm their own password through the durable bounded login throttle. Native identity and local authority are rechecked after that wait. Administrator/self targets are protected; ordinary targets require an exact enabled version.
The atomic local transaction disables the target, increments its version, deletes bound password sessions and appends an actor-bound account event. Dependent Golf API credentials lose their source sessions; enabled repository automation grants for that local sponsor are permanently revoked in the same transaction. Wrong password, stale version, protected role and changed authority fail; a lost response requires inspection rather than automatic retry. Independent PAT/OAuth sessions and native Git keys remain separate. Ordinary enrollment/reset/enable now have password-confirmed APIs; role changes, administrator recovery and live database cutover remain operator-managed; CLI/MCP delegated allowlists are unchanged. See the disable contract. See the instance contract.
Repository general settings
Both RepositorySettingsService procedures require a live browser session and exact Origin. Read-only Golf API credentials are denied. GetRepositorySettings takes repository: {owner, name} and returns settings containing repositoryId, ownerId, description, defaultBranch, hasIssues, hasWiki, hasPullRequests, canEdit and revision. Native repository readers can view; editing requires current native repository administration and a credential with write access. Archived/mirrored repositories are read-only.
UpdateRepositorySettings takes the repository key, immutable repositoryId/ownerId, expectedRevision and at least one optional changed field: description, defaultBranch, hasIssues, hasWiki or hasPullRequests. Omitted fields are unchanged; explicit empty description and false flags are updates. IDs are canonical positive decimal strings. Description allows up to 2,048 UTF-8 bytes; default branch must already exist and pass the shared ref validator. Native administration/local authority are rechecked before PATCH, followed by receipt validation and independent readback.
Revision mismatch is failed_precondition. This catches stale observations before dispatch; it is not atomic native compare-and-swap. External concurrent edits can race. A lost response or failed readback may follow an applied write: refresh/inspect instead of retrying automatically. No durable mutation journal or policy audit is added. These flags do not implement CI, branch protection, merge governance or agent policy. See settings and the product contract.
Personal repository collaborator access
RepositoryAccessService has five browser-session-only procedures; exact Origin, current native identity/authority and no-store boundaries apply. Delegated read credentials are denied.
| Method | Request and response |
|---|---|
GetRepositoryAccess | repository returns access: repositoryId, ownerId, owner, organizationOwned, canManage, revision, currentPermission. Authorized readers can inspect metadata after positive owner-kind classification. |
ListRepositoryCollaborators | repository, immutable repositoryId/ownerId, expectedRevision and page return collaborators plus page. Inventory requires qualified personal repository administration. |
ResolveRepositoryCollaborator | Same identity/revision fields plus userLogin return one exact existing collaborator for review. |
SetRepositoryCollaborator | Resolve fields plus immutable userId, original expectedCollaboratorRevision and permission (read, write, admin) return verified collaborator. |
RemoveRepositoryCollaborator | Same mutation identity/revision fields without permission return collaborator with direct membership absent. Effective public/native permission can remain. |
A collaborator contains user, observed native permission, independent isDirect and revision. Permission is effective native authority, not a claim of exact direct grant metadata. Only actual personal owners or qualified direct native admins manage grants; native site-admin owner observations do not override Golf ownership. Organization repositories remain read-only, hidden owner-kind classification fails closed, and owner/caller-self/exceptional owner-level targets are locked.
Requests bind the original reviewed repository and target observations. Stale revisions and immutable identity mismatches fail before a single supported native write; a verified receipt is followed by independent readback. Username-addressed writes have no atomic immutable-ID or policy lock: external changes may race. Unknown writes require fresh inspection and separate review, without automatic retries or a durable journal. See access settings and the contract.
Workflow configuration inspection
WorkflowService.InspectWorkflows accepts repository and optional ref, resolves it once and returns string repositoryId, commitId, catalogVersion, executionAvailable, configurations and discovery diagnostics. It requires a current browser session and native read authority; delegated API/CLI/MCP allowlists are unchanged. executionAvailable reports configured runner keys and approved images; it is not a guarantee of a currently live worker, policy approval or successful execution. Dispatch rechecks current authority and all eligibility ceilings.
Each configuration exposes path, blobId, uint64 byteSize, format/state enums, display name, bounded jobs, events and fixed diagnostics (code, message, uint32 line/column). Job summaries include id, name, stage and uint32 stepCount. Commands, secrets and raw YAML are excluded from this result; existing source reads have separate authorization.
Discovery covers direct .github/workflows/*.yml/*.yaml and root .gitlab-ci.yml. It verifies content bytes against Git blob identity at the pinned commit. Limits are 20 files, 64 KiB per inspected file and 512 KiB aggregate eligible bytes; oversize files stay metadata-only and overfull requests fail visibly. YAML structure/diagnostics have additional explicit bounds. No matching files is a successful empty inventory.
WORKFLOW_INSPECTION_STATE_VALIDATED_SUBSET means Inspection subset checked, not provider compatibility, a safe script, available runner or successful check. UNSUPPORTED and INVALID remain visible. The bounded one-job Actions/GitLab static catalog does not evaluate expressions, fetch includes/actions, activate triggers or dispatch jobs. See workflow source inspection and the contract.
Protobuf JSON rules
Field names are camelCase: fullName, defaultBranch, commitId, createdAt, updatedAt and htmlUrl. Generated clients reconstruct omitted default values and empty arrays. Do not infer an error because a raw JSON response omits a default field.
- User, repository, issue, pull-request, review, organization, team, session-management, SSH-key, creation-operation and audit-event IDs are opaque decimal strings. Preserve them as strings, including values beyond JavaScript's safe integer range. A management ID cannot authenticate a request.
- File sizes and
revokedCountareuint64: decimal strings in JSON andbigintin the generated TypeScript model. Do not convert them through JavaScriptNumber. - Commit-diff
byteSizeis uint32 and a JSON number, bounded to 524,288; it is not the uint64 source-entry size. Diff base enums areCOMMIT_DIFF_BASE_ROOTandCOMMIT_DIFF_BASE_FIRST_PARENT. - Source kinds use
SOURCE_ENTRY_TYPE_DIRECTORY,SOURCE_ENTRY_TYPE_FILE,SOURCE_ENTRY_TYPE_SYMLINKorSOURCE_ENTRY_TYPE_SUBMODULE. Generated TypeScript exposes the corresponding enum members. - Issue and pull-request filters use
ISSUE_STATE_OPEN,ISSUE_STATE_CLOSEDorISSUE_STATE_ALL; an unspecified filter defaults to open. Capability JSON uses names such asCAPABILITY_STATE_READY,CAPABILITY_STATE_DEGRADEDandCAPABILITY_STATE_DISABLED. - Optional
privatemust be present when creating a repository. Explicitfalsemeans public; omission is rejected rather than silently creating public code. - Optional file
contentdistinguishes an empty text file ("") from an unavailable preview (field absent).
Session, SSH-key, repository, issue, PR and organization/team collection pagination is nested. Account activity uses the separate keyset contract below. Requests use {page: {page: 1, limit: 20}}. Zero or omitted request values use page 1 and limit 20; maximums are page 10,000 and limit 100. Responses use page.nextPage; zero or an omitted next-page value means completion. Neither browser nor CLI should pretend the first page is the full result set.
Durable repository creation
CreateRepository accepts name, description, explicitly present private and optional idempotencyKey. A supplied key must be a canonical lowercase UUID v4. It binds the exact name/description/visibility to the immutable Golf account and configured forge; changing any value with that key returns failed_precondition. Keys do not authenticate requests. Names use the existing 1–100 character repository-name grammar, descriptions are valid UTF-8 up to 2,000 bytes, and omitted visibility is invalid.
Before a provider POST, Golf commits an OUTCOME_UNKNOWN record and initial event. Only the inserting transaction can dispatch; duplicate keys never redispatch, including after restart, cancellation or timeout. A reservation can remain unknown even if it never reached the provider. This is a one-dispatch rule for this endpoint, not exactly-once native execution or a general worker/outbox.
Both create and inspection return creation and an optional repository. Creation fields are id, idempotencyKey, state, requestedName, private, createdAt, updatedAt, repositoryId and failureCode. The ID and native repository ID remain opaque decimal strings; timestamps are RFC 3339. Raw Protobuf JSON may omit default empty fields. State names are:
| JSON state | Meaning |
|---|---|
REPOSITORY_CREATION_STATE_OUTCOME_UNKNOWN | Reserved, in flight, never dispatched or completed without usable/committed evidence; no automatic retry or adoption |
REPOSITORY_CREATION_STATE_SUCCEEDED | Committed native success bound to the requested owner/name/visibility and exact positive repository ID |
REPOSITORY_CREATION_STATE_REJECTED | Committed native HTTP 400/401/403/404/409/422 rejection, categorized as provider_http_<status> |
Only success has a recorded repositoryId; native error bodies and the description are not returned as operation diagnostics. Other provider statuses, transport failures and invalid/oversized results remain unknown. Keyed create calls can return HTTP 200 with a rejected or unknown record: check the state. Omitting the key retains older RPC error behavior, such as permission_denied or already_exists, while still reserving a generated intent; successful responses include its key. Repeating an unkeyed call is a new intent, not a deduplicated retry.
GetRepositoryCreation({idempotencyKey}) requires read:user and fresh matching provider identity. Missing and foreign keys both receive not_found; expired/revoked callers receive no record. Creating through a PAT requires write:user plus write:repository. Current repository metadata also depends on the caller's native repository permission/scope: Golf re-reads the recorded path and requires the original ID. Deletion, rename, scope/access loss or replacement can return a historical SUCCEEDED record without repository; transient provider read failures remain visible errors. Success evidence does not authorize the repository today.
The browser freezes one intent, offers status inspection and resumes inspection only after reload. The CLI's repo creation UUID calls the read procedure and cannot dispatch. See the creation guide for retry/recovery boundaries and the source contract for qualification. Session revocation cannot undo a native write already admitted.
Account session operations
ListSessions returns sessions and page. Each session contains only id, createdAt, expiresAt, current and credentialKind; the kind is local, pat or oauth. Times are RFC 3339 strings. The ID is a non-credential handle, separate from the opaque authentication cookie. No token, verifier hash, encrypted envelope, OAuth refresh credential, IP or user-agent data is returned.
Session rows are ordered by descending creation time and then management ID. Offset pagination is not a snapshot across concurrent logins or deletions. Reset to page one after a refresh or mutation and deduplicate loaded IDs. If page 10,000 still has another result, ListSessions returns a visible invalid_argument limit error; it does not silently report completion.
RevokeSession accepts a canonical positive decimal string: leading zeroes, signs, whitespace, zero and values beyond the supported signed 64-bit range are invalid. Missing, expired and foreign sessions all receive not_found. Revoking the caller returns currentSessionRevoked: true and expires its cookie; clients must cancel and remove private queries immediately. A false default may be omitted in raw JSON.
RevokeOtherSessions operates on all other active account sessions, including those outside the loaded page. Its uint64 revokedCount is a decimal string in JSON; the generated client restores an omitted zero as 0n. An authenticated repeat with no other sessions succeeds with zero deletions. A competing request whose own session was revoked receives unauthenticated.
Both PAT and OAuth callers must pass fresh upstream identity verification matching the stored immutable Forgejo user ID. SQL scoping also binds the caller, user and configured forge. Expiry is rechecked after provider/database waits and before commit; failed transactions do not report successful revocations. These operations remove Golf sessions. They do not revoke provider credentials, cancel already authorized repository requests or prevent a new authorized login. See sign-in and sessions and the product's session-management contract.
Own-account SSH keys
GitAccessService requires a live browser session, exact Origin and fresh native identity checks. Read-only golf_ro_ credentials cannot invoke even the list procedure. Native read:user permits listing; write:user is required for add/remove. Native account repository permissions determine what a key can read or write.
ListSSHKeys returns keys and page. Each key has opaque decimal-string id, title, canonical publicKey, SHA256 fingerprint, and RFC 3339 createdAt/lastUsedAt when provided by the backend. These are public-key metadata, never private key material.
An added title is trimmed valid UTF-8, 1–64 bytes without controls. publicKey is one OpenSSH public authentication key up to 8192 bytes; comments are discarded. Options, multiple keys/lines, certificates, private keys, DSA and RSA below 2048 bits are rejected. Ed25519, ECDSA, supported security keys and adequate RSA pass the parser; only Ed25519 transport is qualified by this increment. DeleteSSHKey takes a canonical positive decimal keyId; missing and foreign keys return not_found. Provider HTTP 422 key rejection maps to failed_precondition.
These are persistent broad native account keys. They survive Golf logout, session expiry, password reset and local account disable. Removal denies new SSH connections, with no guarantee of cancelling already accepted connections. There is no read-only account-key flag: the pinned native API did not honor it in the disposable proof. Short-lived/repository-scoped agent credentials, unified suspension and key-use audit remain planned.
Writes have no automatic retry or durable mutation journal. A failed response can follow an accepted native write; refresh and inspect before making another request. See Git access and qualification for use and limitations.
Account activity and snapshots
AuditService.ListAuditEvents requires the caller's valid Golf session and current matching provider identity with read:user. It returns only that immutable account's history. The request has limit (zero/omitted defaults to 20, maximum 100), beforeId and snapshotId; the response contains events, nextBeforeId and snapshotId.
Omit cursors to capture the highest committed account event. Continue with the returned snapshot and next cursor: IDs are ordered descending, eligible IDs are at or below the snapshot, and continuation is strictly below beforeId. New events stay outside that traversal. An empty nextBeforeId ends it; an empty snapshot means no recorded events. Refresh without cursors starts a new capture.
Both cursor values are canonical positive signed-int64 decimal strings through 9223372036854775807. A before cursor requires a snapshot and cannot exceed it. Each supplied ID must refer to an existing event owned by this account; missing/foreign/future IDs receive the same generic invalid_argument. Keep these strings exact. Account locking serializes capture against event writers, including cross-account session replacement; this is a bounded history snapshot, not a provider-state or signed-export guarantee.
Event fields are id, occurredAt, action, actorSessionId, targetSessionId, credentialKind, revokedCount, operationId and optional expiresAt. Actions are AUDIT_ACTION_SIGN_IN, AUDIT_ACTION_SIGN_OUT, AUDIT_ACTION_SESSION_REVOKED, AUDIT_ACTION_OTHER_SESSIONS_REVOKED and AUDIT_ACTION_SESSION_REPLACED. Counts are uint64 JSON decimal strings. Default zero counts/empty targets may be omitted in raw JSON. Expiry is present only on sign-in and describes the new session, not audit retention.
Session handles cannot authenticate requests. The operation ID is nonsecret correlation metadata, not an idempotency key; cross-account replacement records do not expose the other account's handles or correlate them through one shared ID. No credential envelope, token/hash, cookie, OAuth state or device/location inference is returned. The activity guide documents exact event meanings, excluded cleanup/refresh paths, append-only limits and upgrade requirements.
Organization and team reads
Requests identify an organization by its validated name component. Team IDs are canonical positive signed-64-bit decimal strings; leading zeroes, signs and out-of-range values are invalid. Collection responses contain organizations, teams, members or repositories, plus the shared page object. Detail responses wrap one organization or team.
Organization fields are id, name, fullName, description and visibility. Organization JSON visibility is ORGANIZATION_VISIBILITY_PUBLIC, ORGANIZATION_VISIBILITY_LIMITED or ORGANIZATION_VISIBILITY_PRIVATE. Team fields are id, name, description, permission, unitPermissions, includesAllRepositories and visibility; its visibility uses the equivalent TEAM_VISIBILITY_ prefix.
Team permission values use TEAM_PERMISSION_NONE, READ, WRITE, ADMIN or OWNER with that same prefix on each value. unitPermissions maps native keys such as repo.code and repo.issues to those enums. Unknown provider visibility, permission or unit metadata fails visibly. The legacy team permission may be NONE while a unit grants WRITE; clients must preserve both instead of deriving a Golf role. Returned member objects use the existing limited User fields, without provider email/admin properties.
Each call verifies the live provider user against the session's immutable identity. Detail and nested calls require a successful self-membership check before and after provider reads. A team must belong to the requested organization. Public provider metadata or site-administrator visibility does not replace Golf's membership requirement. Missing scope and native private-team denial can receive permission_denied; missing organization membership or a foreign team binding receives not_found. Provider denial remains an error, never an empty successful list.
An empty team-repository page can still return page.nextPage: Forgejo filters inaccessible assignments after native pagination. Continue while that field is nonzero. Unfiltered provider totals are omitted. At page 10,000, a provider next-page indication becomes a visible invalid_argument error, not a false completion signal. No collection is a snapshot across concurrent membership changes.
Use read:user plus read:organization; opening code separately needs read:repository. For an older OAuth grant without that scope, revoke the existing grant under Forgejo Settings → Applications before starting fresh consent; repeating sign-in or refreshing cannot upgrade it. See organization workflows and the product's organization contract. The six CLI commands use these same procedures. These reads add no membership mutations or managed Golf roles.
Pull-request and review reads
ListPullRequests returns pullRequests and page; GetPullRequest wraps one pullRequest; ListPullRequestReviews returns reviews and page. Detail/review numbers are 1–2147483647. All three use the caller's repository authorization and read:repository, with read:user for sign-in; they do not require read:issue.
Pull-request metadata includes the native draft, merged, mergedAt and mergeCommitId values. Its head and base each expose repositoryId, label, ref, commitId and retainedSnapshot. List heads are retained PR snapshots even when their ref displays a branch name. Detail may resolve an observed source branch or a retained fallback; retainedSnapshot: false does not prove freshness. Preserve IDs as strings and absent source identities as unavailable.
Review state uses the PULL_REQUEST_REVIEW_STATE_ enum with APPROVED, PENDING, COMMENT, REQUEST_CHANGES or REQUEST_REVIEW. stale, dismissed and official are native flags; they do not compute Golf approval eligibility. A deleted/unavailable author has no substitute user identity. Bodies remain plain text.
An empty review page may still have page.nextPage because Forgejo filters pending records after pagination. Follow that field until zero/absent; at the supported page ceiling an additional page fails visibly. Resource denial stays an error, not a successful empty collection. Native PR reads can cause provider-side checking work; these Golf read procedures do not establish a mutation-free Forgejo boundary. See pull-request workflows and protected-write limitations.
Immutable commit diffs
GetCommitDiff accepts {repository: {owner, name}, commitId}. The commit ID is exactly 40 or 64 lowercase hexadecimal characters; branches, abbreviated IDs and revision expressions are rejected. This syntax does not qualify every repository object format. There are no page, arbitrary-base or file-filter arguments. Existing read:user plus read:repository scopes are sufficient.
The response fields are commit, parentCommitIds, baseCommitId, base, rawDiff and byteSize. Commit metadata uses sha, message, authorName and authoredAt. Roots use COMMIT_DIFF_BASE_ROOT, no parents and an empty base ID. Every nonroot (including a merge) uses COMMIT_DIFF_BASE_FIRST_PARENT and its first native parent; all parent IDs remain visible in order. This is not a combined merge or PR comparison. Raw JSON may omit empty/zero defaults, while generated clients restore them.
The raw UTF-8 text is limited to 512 KiB, with controls other than tab/LF/CR rejected. byteSize is a uint32 JSON number representing accepted UTF-8 bytes. Oversize returns resource_exhausted; unsupported encoding/control text or an empty repository returns failed_precondition. There is no partial/paginated/truncated-success mode. An empty native diff remains a successful empty text result, distinct from a missing commit.
Metadata must bind to the exact SHA, valid author timestamp and explicit parent list with at most 1,000 same-length full IDs; provider JSON is limited to 2 MiB. A metadata commit URL must be well-formed HTTP(S) without userinfo, query or fragment and match the repository’s exact escaped path plus /commit/SHA. Its origin may differ because Forgejo’s API repository metadata and commit metadata use different request/public-root contexts. Golf neither follows nor returns that URL. Immutable caller identity, repository name/ID/access and local session validity are checked around provider waits.
Native binary notices, escaped filenames, mode/symlink/gitlink changes and root git show metadata (including commit author email) remain plain text. Golf does not expand binary objects or parse a structured patch. An HTTP 200 provider stream can end after an internal formatter failure without a completion marker; detectable transport failures are rejected, but accepted bytes are not independently verified patch completeness, signed evidence or merge eligibility. Exact object IDs fix selection, not formatter bytes across provider settings. See the browser workflow and the product’s diff contract.
Source snapshots
A content response has commitId, path, enum kind, and either entries or file. A file wraps its metadata in file.entry; text is in file.content, and excluded previews have file.previewReason.
For example, this illustrative response describes an empty text file. The optional content is present even though its value is empty:
{
"commitId": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"path": "empty.txt",
"kind": "SOURCE_ENTRY_TYPE_FILE",
"file": {
"entry": {
"name": "empty.txt",
"path": "empty.txt",
"type": "SOURCE_ENTRY_TYPE_FILE",
"sha": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"size": "0"
},
"content": ""
}
}
Reuse the returned commitId as the next request's ref when traversing related files. Resolve or reselect the branch to observe a new head. Text remains plain UTF-8 up to 256 KiB; metadata-only reasons cover binary, large, LFS, symlink and submodule content. Oversized directories or responses fail visibly. See preview limits and the product's repository contract.
Typed failures
Connect JSON errors use {code, message}. Generated clients expose typed ConnectError codes; a client should inspect the code instead of matching prose.
| Code | HTTP | Meaning |
|---|---|---|
unauthenticated | 401 | Missing, expired or revoked session/credential |
permission_denied | 403 | Scope, provider-access or request-origin permission failure |
not_found | 404 | Resource absent or inaccessible; these cases remain indistinguishable |
invalid_argument | 400 | Invalid input or pagination |
failed_precondition | 400 | Empty source/diff repository, unsupported diff text, or reused creation key with different inputs |
already_exists | 409 | Native repository-name conflict for a legacy unkeyed create call |
resource_exhausted | 429 | Supported source/response bounds exceeded |
unavailable | 503 | Provider or storage could not serve the operation |
Empty repository branch/history results are normal empty lists. The first Git push can briefly retain empty metadata while Forgejo finishes processing; unrelated provider failures must not be presented as empty repositories.
Contract maintenance
Run make generate and make generate-check in the product checkout when changing the schema. Generation uses the product's pinned tools; generated Go/TypeScript clients and SQL queries are committed there. Existing field numbers must be preserved, and removed numbers reserved before future published contract changes.
A schema package named v1 and the CLI's golf.cli.v1 envelope do not declare a stable product release. Broader identity, invitations/team-grant/ownership mutations, full native-engine CI, agent execution, deployment, remote MCP and ACP services remain future work; the policy/manual-job increments described above are bounded current services. Local stdio MCP exposes only the already implemented reads documented in its separate contract. Any later generated API reference must record its exact product commit/tag, schema digest and generator version rather than creating another hand-maintained contract.
Owner-issued read-only credentials
ApiCredentialService adds browser-session-only issue/list/revoke. Golf API credentials authorize an explicit current-read allowlist plus identity inspection, with source-session expiry/revocation coupling; writes and credential management are denied. This bearer transport is not an OAuth authorization server.
Issue discussions
See discussion input, paging and uncertainty boundaries. IssueMutation records kind, target IDs, state and optional provisional observedResultId/observedNumber. Provisional metadata does not turn UNKNOWN into success. Native POST addresses cannot atomically fence a target rename/delete/reuse; protected/conditional target gates remain open. API credentials can inspect comments/own operation status but cannot invoke creation.
RefreshCodexConnection now also returns an optional usage snapshot: availability/reason, checked time, separate quota buckets with primary/secondary percentage/duration/reset data, and an optional banked-reset count. The existing connection/version/authentication receipt remains authoritative. Missing count/time is distinct from zero. Manager/session/Origin/CAS checks and native-cache persistence apply across the provider wait; no reset redemption or inference operation is exposed.