sx-gitea Phase 4: issues — content-document bodies + relations graph (TDD, 360/360)

lib/gitea/issues.sx: issues as kv records (zero-padded per-repo
numbering, title/author/state, sorted label+assignee sets, Markdown
body, comment thread). Bodies and comments are content-on-sx documents:
content/from-markdown -> block doc -> content/html for pages, with the
round-trip law asserted in the suite. The issue graph (issue->repo
parent, author origin, assignee member, label link, commenter reply) is
DERIVED into lib/relations facts and rebuilt on fact change — same
pattern as the acl db, so deleting a repo can never dangle edges.

Views: open/closed/by-label/by-assignee; graph queries: repo-issue-nodes,
user-authored, user-assigned, label-issues, issue-participants.

Web: issues list + issue page (rendered HTML body + comments), JSON API:
create (any authenticated reader), comment, close/reopen (author or
write), label/assignee management (write). All read-gated like the rest.

Infra: gitea/route-packs registry — wire/issues append their routes at
load; gitea/app serves all packs. repo-delete! now purges collab/issue/
issue-seq rows too (ghost-state regression tested). Conformance runner
gains per-suite extra modules; the issues suite loads relations +
smalltalk + content (~5s).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-03 13:53:21 +00:00
parent 83a8a2f8db
commit d96529effe
8 changed files with 1423 additions and 33 deletions

View File

@@ -11,6 +11,9 @@
; needs the owner (or org admin), delete and collaborator management need
; "admin". 401 = no credentials, 403 = authenticated but not allowed.
;
; Later modules (wire, issues, ...) extend the app by appending a routes
; pack to gitea/route-packs at load time; gitea/app serves them all.
;
; Requires: lib/gitea/{repo,access}.sx, lib/dream/{types,router,middleware,
; error,html,json,auth,api}.sx
@@ -497,4 +500,16 @@
"/:owner/:name/raw/:ref/**"
(fn (req) (gitea/w-raw forge req))))))
(define gitea/app (fn (forge) (dream-make-app (gitea/routes forge))))
; extension point: wire/issues/... append their packs at load time
(define gitea/route-packs (list gitea/routes))
(define
gitea/all-routes
(fn
(forge)
(reduce
(fn (acc pack) (concat acc (pack forge)))
(list)
gitea/route-packs)))
(define gitea/app (fn (forge) (dream-make-app (gitea/all-routes forge))))