Skip to content

Latest commit

 

History

History
351 lines (276 loc) · 15.5 KB

README.md

File metadata and controls

351 lines (276 loc) · 15.5 KB

Self-hosted issue-spec server

English | 简体中文

The self-hosted server brings the issue-native issue-spec workflow to an operator-controlled environment. It combines a browser workspace, a GitHub-compatible issue API, organization and repository authorization, provider-neutral code evidence, webhooks, runners, and durable PostgreSQL state in one deployable service.

Use self-hosting when a team needs private-network deployment, local identity and authorization, internal code-host integration, or automation identities that do not depend on a personal GitHub account.

Repository issue list with repository subscription

What the server owns

Browser and issue-spec CLI
          |
          v
 issue-spec-server  <---->  GitHub OAuth or OIDC
    |       |
    |       +------------>  code-provider bridge / evidence ledger
    |       +------------>  GitHub-compatible or runner webhooks
    v
 PostgreSQL

The server is authoritative for:

  • organizations, repositories, memberships, collaborators, and visibility;
  • issues, comments, labels, reactions, typed workflow projections, and change boards;
  • personal and managed access tokens, service accounts, optional token delegation, source bindings, evidence policies, and immutable evidence;
  • webhook subscriptions, filtering, encrypted credentials, delivery attempts, retries, replay, and audit records.

The external code host remains authoritative for source code, branches, commits, pull requests or merge requests, reviews, and CI. A source binding and code-provider adapter project that evidence into issue-spec without giving the server ambient source credentials.

Product tour

Issues keep the full decision history

Proposal, design, and implementation issues carry the current artifact in the issue body. SPEC, QUESTION, TASK, and PROCESS records are active typed comments in the same timeline. Historical REVIEW and VERIFY records remain visible for audit only. Ordinary human comments remain available for discussion and notifications.

Issue detail with typed workflow comments

Review projections render for humans, questions get native answers

Agents publish sandboxed html-preview review projections for each phase — a proposal choice brief, a design explainer, and an implement execution brief — and every typed QUESTION comment carries a native answer panel. Confirmed choices become immutable typed ANSWER comments that later agents and gates consume.

Design explainer review projection

Search finds canonical Proposals

Full-text search covers canonical Proposal titles and bodies and keeps each match linked to its related change. Comments, ordinary issues, and later Design/Implement artifacts are outside this discovery surface. The same query runs from the CLI with issue-spec search issues --query <text> --state all.

Search results grouped by related change

Change boards show workflow state, not just issue counts

The change board groups proposal, design, and implementation issues into one change. It exposes lifecycle, TASK and PROCESS progress, diagnostics, and linked code changes without making the external code provider the issue backend.

Change board

The detail view keeps traceability and provider-neutral code relationships in one place. A GitHub pull request and an internal merge request can appear under the same change while retaining their provider identity.

Change detail and code evidence

Search recovers earlier decisions before the next change

When the operator enables PostgreSQL search, the browser workspace searches visible canonical Proposal titles and bodies, including closed Proposals, and keeps related change navigation beside each result. Authorization and the Proposal candidate boundary are applied before title/body matching. Search requests accept at most 256 query bytes and 50 results per page, and the server applies a five-second database query deadline while preserving any earlier caller deadline.

Direct Codex, Claude, and other issue-spec clients use the same capability:

issue-spec --profile team search issues \
  --repo acme/workflow \
  --query ListConfigsBySource \
  --state all \
  --limit 10

Search output keeps user-authored titles and excerpts inside untrusted data boundaries and points the agent to read issue --comments for the selected full discussion. This is a general issue-spec workflow; runner-dispatched agents reuse it rather than defining a runner-only search process. See the deployment guide for the explicit extension and startup contract.

Integrations are policy controlled and auditable

Repository administrators can configure runner intake or github.v3 notification webhooks. Notification policies can select issue actions, change kinds, human or typed comments, and human or automation actors. Query credentials are encrypted and never returned to the browser after creation.

Webhook delivery control room

Access model

Repository visibility controls reads. Contribution policy separately controls who may create issues or comments.

Visibility Anonymous Authenticated outsider Member or collaborator
public read read read
internal concealed read read
private concealed concealed read
Contribution policy Who may contribute
disabled nobody
members organization members, service accounts, or explicit collaborators
authenticated any active signed-in identity
public any active signed-in identity when repository visibility is public

Anonymous mutation is always denied. Signing in through GitHub OAuth or OIDC creates an external identity; it does not implicitly grant an organization role, repository permission, runner authority, or evidence publication authority. Evidence publication additionally requires explicit credential scope and live repository permission.

Deployment path

The production artifact is a single issue-spec-server binary or the repository runtime container. The binary embeds the generated web application. PostgreSQL and three operator-owned secret files are required. A fourth, optional SMTP secret file enables verified notification email, mentions, and explicit repository email subscriptions; leaving it absent keeps those capabilities disabled without affecting issue or webhook operation.

  1. Read the deployment and hardening guide.

  2. Choose HTTPS or complete the trusted internal HTTP checklist.

  3. Configure GitHub OAuth or OIDC.

  4. Build a reproducible server artifact:

    make release-server
    # or
    make docker-server IMAGE=registry.example/issue-spec-server:VERSION
  5. Start PostgreSQL and the server with the required environment and secret mounts. Wait for /readyz before routing employee traffic.

  6. Claim bootstrap once, sign in with the configured provider, create the first organization, and assign local roles explicitly.

  7. Back up PostgreSQL together with the token pepper and encryption keyring; see backup, restore, upgrade, and recovery.

The deployments/dev fixture is for local development. Follow the local Server development guide to run the complete Compose stack or a host-built binary against its PostgreSQL service. Do not copy its credentials or development posture into production.

Connect a local repository

For the complete external-user path—from verified CLI installation and a name-only PAT through a simple issue or standard Proposal/SPEC—follow Start a requirements workflow.

Create a PAT from Access tokens in the web application, then configure an origin-bound self-hosted profile. Read the canonical origins and instance ID from /api/v1/meta instead of guessing them.

printf '%s\n' "$ISSUE_SPEC_TOKEN" | issue-spec auth login \
  --profile team \
  --kind self-hosted \
  --api-url https://issues.example.com \
  --native-api-url https://issues.example.com/api/v1 \
  --web-url https://issues.example.com \
  --instance-id issue-spec:00000000-0000-4000-8000-000000000000 \
  --with-token

issue-spec --profile team auth status --json

Initialize an existing server repository:

issue-spec --profile team init \
  --repo acme/workflow \
  --server-org acme \
  --server-repo workflow \
  --tools codex,claude \
  --delivery both

An authorized caller may add --create-if-missing to register the repository. Use --bind-source, --provider, and the external repository coordinates when the source lives on a separate code host. Source bindings contain canonical repository identity and URLs, never a personal clone credential.

After a provider-owned PR/MR already exists, validate and attach its exact head revision to the Implement Issue, then link each PROCESS through the same active relationship:

issue-spec --profile team code-change attach \
  --repo acme/workflow --implement 3 --change-id 42 --revision abc123 --json

issue-spec --profile team code-change link-process \
  --repo acme/workflow --implement 3 --process PROCESS-001 \
  --expected-version 5 --json

The Source Binding supplies provider and external repository identity. code-change attach neither creates the external change nor ingests evidence; refresh requires --refresh and --expected-version together. Linking requires exactly one active code_change. If references are ambiguous, inspect them, delete only the unwanted active reference, and retry—never guess or silently overwrite. GitHub keeps its existing PR workflow; self-hosted review, merge, and closure stay with the selected code provider.

When Design or TASK is selected, or the user requests delegation, the Coordinator writes no code on delegated or managed paths. Without managed PROCESS, exactly one real non-Coordinator worker owns the bounded implementation; with managed PROCESS, each change-bearing package has one worker owner and distinct packages may run concurrently. Coordinator edits are limited to a narrow direct-PR fast path with neither selected planning nor a delegation request. The delegated worker, narrow fast-path writer, or each managed PROCESS worker returns zero or more line-rationale drafts for non-obvious decisions: repository-relative path, stable symbol plus changed-line anchor, and why/tradeoff/risk, with no secret, raw payload, or credential. Writers need no provider permission and never guess final diff positions. After the exact head is integrated and pushed, the coordinator validates anchors, continued applicability, and sensitive-data absence, then publishes unchanged worker text as non-blocking provider-native inline discussion. Invalid, stale, or sensitive drafts return to the writer or are dropped with explanation, never rewritten under worker authorship. There is no quota; obvious code produces no inline comment.

Before human review, publish or refresh the ordinary top-level ### Implementation Rationale discussion as summary and inline-comment index. If non-blocking inline discussion is unsupported or would create an unresolved merge blocker, keep path:symbol/line plus the worker rationale in this top-level discussion and do not create the blocking thread. These discussions are mutable review UX with no typed carrier, rationale ID, PROCESS/SPEC binding, evidence field, gate, or merge effect. Report required provider write failures and retain the rendered body for retry or manual publication.

After pushing the exact head and creating or selecting its PR/MR, report the change link, tests, rationale, risks, and provider-operation limitations, then stop. Provider-native CI, review, approval, merge, and closing behavior remain in the provider UI under human control; issue-spec creates no readiness state or post-merge reconciliation step.

For a provider-neutral integration plan, operator registry example, bridge scaffold, code-evidence mapping, and Jira-like work-item projection pattern, read Integrate company code and work platforms.

Automation identities

A service account is an organization-bound non-human identity for CI, runners, evidence synchronization, or scheduled integrations. Creating one does not create a token or grant repository authority.

The safe sequence is:

  1. create the service account;
  2. grant only the required repository collaborator role;
  3. create a managed PAT with the required scopes and either site-wide access or an explicit repository cap;
  4. store the one-time token in the automation secret store;
  5. disable the service account to invalidate its credentials when retired.

An organization administrator may issue a site-wide managed PAT for an enabled service account owned by that organization. Human members normally create their own site-wide personal PAT; only a site administrator may issue or rotate a site-wide managed PAT on their behalf. Site-wide means the token follows the subject's live permissions—it does not grant repository authority by itself.

Service-account and PAT activity is classified as automation, allowing webhook policies and audit review to distinguish it from human browser activity.

Webhooks and runners

Two delivery contracts share the same transactional outbox and delivery ledger:

  • issue-spec.v1 uses bearer authentication for issue-spec runner serve;
  • github.v3 emits GitHub-compatible issue and issue-comment events for notification receivers such as a GitHub-compatible DingTalk robot.

Typed comments and automation actors can be excluded without parsing untrusted comment text. Failed deliveries are retried, become dead letters after the configured attempt limit, and can be replayed without changing event identity. For multi-replica behavior and recovery, read HA webhook delivery operations. For the complete PAT, source binding, webhook, systemd, and comment-command setup, see Self-hosted runner: trigger agents from issue comments.

Operations index

Regenerate the documentation screenshots

The images in this guide are not captured from a real organization. They are generated from deterministic, credential-free Playwright fixtures also used by the visual regression suite.

make docs-self-hosted-screenshots

The command builds the web application, updates the English and Simplified Chinese desktop golden snapshots, and copies both documentation variants into docs/self-hosting/assets. Review visual diffs before committing regenerated images. Never replace these fixtures with screenshots from an internal deployment, real issue content, access tokens, or employee identities.