docs(ISSUE-WP-0006): Forgejo-only language and projection boundary
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 2s
Build and Publish Container Image / build-and-push (push) Successful in 34s

Prefer Forgejo as the self-hosted forge product. Keep Gitea only as the
Gitea-compatible API identifier (module backends/gitea, type string
gitea). FORGEJO_TOKEN is preferred; GITEA_* remains a deprecated alias.

INTENT/SCOPE quote ACT-ADR-005: issue-core is not the fleet ops claim
queue. Connector docs describe repo work record → hub index → optional
Forgejo projection, not activity-core → issue-core → harness.

Assistant: grok
Assistant-Session: 01a09dc6-3f0d-7c93-8b11-8e83c0623d49
This commit is contained in:
tegwick 2026-09-14 04:52:58 +02:00
parent f9d276dadf
commit ee9b85215d
34 changed files with 410 additions and 263 deletions

View file

@ -25,7 +25,7 @@ aspirational lists when deciding “does issue-core already do X?”
| Concept | Notes |
| --- | --- |
| `Issue` | id, number, title, description, state, timestamps, labels, assignees, milestone, comments, backend_id/type, `sync_metadata` |
| `IssueState` | `open`, `closed`, `in_progress`, `blocked` (Gitea maps non-closed → open on the wire) |
| `IssueState` | `open`, `closed`, `in_progress`, `blocked` (Forgejo Gitea-compatible API maps non-closed → open on the wire) |
| `Label` / priority / type | Priority and type are primarily **label conventions** (`priority:high`, `bug`, …), not separate backend columns everywhere |
| `User`, `Milestone`, `Comment` | First-class models on the backend interface |
| `Priority`, `IssueType` enums | Helpers for label-derived classification |
@ -46,7 +46,7 @@ aspirational lists when deciding “does issue-core already do X?”
| Backend | Module | Role |
| --- | --- | --- |
| **Local SQLite** | `issue_core.backends.local` | Offline store; hard delete supported; bulk ops; sync-capable |
| **Gitea** | `issue_core.backends.gitea` | Remote REST; **Forgejo-compatible** in railiance01 deploy; no true delete (close-as-delete); rate-limit aware; sync-capable |
| **Forgejo** | `issue_core.backends.gitea` | Remote REST via **Forgejo (Gitea-compatible API)**; backend type string remains `gitea`. Gitea is not a second product. No true delete (close-as-delete); rate-limit aware; sync-capable |
**Not implemented as code:** GitHub, GitLab, Jira backends (optional deps may be
declared in `pyproject.toml`; no backend package under `issue_core/backends/`).
@ -64,7 +64,9 @@ declared in `pyproject.toml`; no backend package under `issue_core/backends/`).
- JSON-friendly output for agents (`--format=json` on list/show paths).
- Backend configs: `~/.config/issue-tracker/` (default backend + named configs).
- Mapping store: `~/.config/issue-tracker/mappings.db` (independent of CRUD backend).
- Gitea token typically from env (`GITEA_API_TOKEN` / config); never commit secrets.
- Forgejo token from env: **`FORGEJO_TOKEN`** (preferred) or `FORGEJO_API_TOKEN`;
legacy **`GITEA_API_TOKEN` / `GITEA_TOKEN`** are deprecated aliases the CLI
still accepts. Never commit secrets.
### 1.4b Work-record mapping (shipped v0.2.x)
@ -103,7 +105,7 @@ also `sync_metadata.mapping` and a row in `mappings.db`.
### 1.6 Synchronization (CLI)
- Bidirectional pull/push between configured backends (e.g. Gitea ↔ local).
- Bidirectional pull/push between configured backends (e.g. Forgejo ↔ local).
- Uses `get_issues_modified_since` / conflict hooks where backends implement them.
- Conflict handling is basic (operator / force flags) — not a full merge engine.
@ -111,7 +113,7 @@ also `sync_metadata.mapping` and a row in `mappings.db`.
| Artifact | Provides |
| --- | --- |
| PyPI package | Built wheel/sdist; Makefile targets publish to Coulomb Gitea/Forgejo registry |
| PyPI package | Built wheel/sdist; Makefile targets publish to Coulomb Forgejo registry |
| Docker image | Built and published by this app repo; production consumes an immutable digest |
| `rapp-issue-core` | Authoritative railiance01 runtime package: manifests, private Service, ExternalSecret references, NetworkPolicy, rollout, rollback, and live evidence |
| `docs/package-release.md` | Release notes for packaging |
@ -148,7 +150,7 @@ Things this repo **owns** and may grow, consistent with the connector role.
backends when tracker use is intentional.
- List and filter (state, labels, assignee, milestone, text search as backends allow).
- Label, assignee, and milestone management through the backend interface.
- Delete where the backend allows (SQLite hard delete; Gitea effectively close).
- Delete where the backend allows (SQLite hard delete; Forgejo effectively close).
### 2.2 Connector / mapping (owned direction)
@ -164,7 +166,9 @@ Things this repo **owns** and may grow, consistent with the connector role.
### 2.3 Surfaces
- CLI for humans and agents on a shell.
- REST for intentional automation and worker claim/list/close.
- REST for intentional **external tracker** create/link and worker
list/update/close of tracker issues. This is **not** the fleet ops claim
queue (ACT-ADR-005 / activity-core `ops_run`).
- Python library for embedding.
- Optional future NATS consumer **only** for intentional external projection
(never silent fleet work origin).
@ -204,6 +208,24 @@ activity-core (and peers) must not treat `POST /issues/` as the always-on
default for every matched rule. Emitters own that policy; issue-core keeps
accepting authenticated POSTs without advertising itself as a landing zone.
Follow-up: `activity-core` **ACTIVITY-WP-0022** (from ISSUE-WP-0004-T05).
Default activity-core sink remains **state-hub progress + `ops_run`**, not
REST to issue-core for Binky/FI.
### 3.3b Ops claim queue (ACT-ADR-005) — not this repo
Internal scheduled automation **claim/execute** belongs to activity-core
**`ops_run`** ([ACT-ADR-005](../activity-core/docs/adr/adr-005-ops-runs-vs-dev-work-records.md)).
issue-core does **not** provide the fleet ops claim queue. Do not poll
`GET /issues/` as “the automation queue.”
ACT-ADR-005: *issue-cores correct role is a connector facade over
external trackers (Forgejo, GitHub, Jira, …). It is not the origin of
work records and not the default internal ops queue. Gitea is out of
scope for this fleet; the self-hosted forge is Forgejo.*
`POST /issues/` = external tracker create/link only. rein-aharness
`poll --source=issue-core` is **legacy / external ticket** path only
(see ISSUE-WP-0006, REINAH-WP-0005-T06).
### 3.4 Project management
@ -246,8 +268,8 @@ Emitters record who/what spawned an external issue (e.g. activity-core
| --- | --- | --- |
| Human / agent shell | CLI | Tracker admin; `project` / `map` for work-record links |
| Library consumers | Python API + `MappingService` | Same backends + mapping store without shell |
| Workers (e.g. harness) | REST GET/PATCH | List / claim / close external issues when in the loop |
| activity-core IssueSink | REST POST | **Optional, intentional** external issues only — not default for internal findings; may pass `work_record_uuid` |
| Workers (e.g. harness) | REST GET/PATCH | List / update / close **external tracker** issues when that tracker is in use — **not** the fleet ops claim queue |
| activity-core IssueSink | REST POST | **Optional, intentional** external issues only — not default for internal findings or Binky/FI; may pass `work_record_uuid`. Default sink is state-hub progress + `ops_run` (ACT-ADR-005) |
| Mapping-aware emitters | CLI or POST `/issues/` with UUID | Project/link work-record UUID ↔ external id |
### 4.3 TaskSpec contract (`POST /issues/`)
@ -287,14 +309,16 @@ Retained for intentional emits and backward compatibility:
```
`issue_id` is the **backend** issue identity for the emitters log; not a
work-record UUID. (`github` appears in the response enum for forward
compatibility; no GitHub backend is shipped yet.)
work-record UUID. The wire value `gitea` is the Forgejo (Gitea-compatible
API) backend type string — not a second Gitea product. (`github` appears in
the response enum for forward compatibility; no GitHub backend is shipped
yet.)
### 4.4 Credential routing (operators / agents)
| Need | Owner |
| --- | --- |
| Gitea/Forgejo API token for backend | OpenBao / operator path (`warden route`) |
| Forgejo API token for backend (`FORGEJO_TOKEN`; legacy `GITEA_*` alias) | OpenBao / operator path (`warden route`) |
| `ISSUE_CORE_API_KEY` for REST | Shared secret via deploy secrets (e.g. ExternalSecret) |
| SSH certs | ops-warden only |
@ -309,7 +333,7 @@ issue_core/
core/ # models, IssueBackend ABC, factory, MappingService
backends/
local/ # SQLite issue store
gitea/ # Gitea/Forgejo REST
gitea/ # Forgejo REST (Gitea-compatible API)
cli/ # Click: issue, project, map, backend, sync, serve
api/ # FastAPI: ingest + query (+ auth, schemas)
tests/
@ -326,7 +350,7 @@ tests, image construction, and Forgejo image publication.
| Language | Python 3.8+ |
| CLI | Click |
| HTTP | FastAPI + Pydantic v2 + uvicorn (`[api]` extra) |
| HTTP client (Gitea) | requests |
| HTTP client (Forgejo) | requests |
| Issue store (local) | SQLite (`issues.db`) |
| Mapping store | SQLite (`mappings.db`, separate file) |
| Tests | pytest |
@ -350,3 +374,5 @@ tests, image construction, and Forgejo image publication.
(issue-core issues = external projections only)
- `the-custodian/research/WorkOrchestrationArchitectureDraft.md` §4.2
- activity-core IssueSink / **ACTIVITY-WP-0022** — emitter-side default policy
- activity-core **ACT-ADR-005**`ops_run` is the fleet ops claim queue; not issue-core
- `workplans/ISSUE-WP-0006-forgejo-only-projection-boundary.md` — Forgejo-only + projection boundary