Deleting a comment removed every reply under it, through the parent_id ON DELETE CASCADE. Now delete removes only that comment: one with replies becomes a tombstone (deleted_at set, body/attachments/reactions/resolution cleared) so the replies keep their parent, and one without replies is removed along with any tombstone ancestor left empty.
Tombstones are read-only and are never agent input. Every write to a comment's children takes its owners first (issue -> comment -> child), and a comment commits together with the attachments it was posted with. Clients only promise that replies are kept when the server declares comment_delete_keep_replies_supported, and then delete through DELETE /api/comments/{id}/keep-replies, which older servers do not route.
Multica Public API v1
This package is the source of truth for the first versioned Public API slice:
openapi.yamldefines the wire contract.routes.gois the capability ledger used by router and contract tests.types.gocontains DTOs that are deliberately independent from App API responses and database models.problem.godefines the stable error envelope used before and after routing.foundation.godefines actor, credential, pagination, idempotency, revision, risk, audit, and rate-limit vocabulary shared by every future resource slice.
The Plugin API is the first deployed surface. Its installation/callback tokens,
manifest scopes, rate limits, and audit policy narrow the shared resource
contract. Plugin context and storage are marked plugin_extension and are not
implicitly part of a future user/PAT surface.
Both surfaces should call the same Go service and handler layer. The Plugin API must not make an additional HTTP request to the user/PAT API.
Additive fields and endpoints remain in v1. A breaking wire change requires a
new major version and a migration window. New write operations should adopt the
shared Idempotency-Key and revision/ETag components rather than inventing
endpoint-specific concurrency rules.
Foundation rules
- User OAuth and PAT authenticate a member; Plugin installation and invocation credentials authenticate either a member-bounded invocation or the installation itself. Authentication happens at the surface, before a shared resource service runs.
- Collection endpoints use opaque cursor pagination with
limit(default 50, maximum 200) and returnnext_cursor. The migrated comment endpoint keeps its existing newest-200 compatibility window until its dedicated pagination slice lands; it is not a precedent for new collections. - Create, trigger, replay, and retry operations must durably deduplicate an
Idempotency-Key(maximum 255 bytes) before the operation is documented as idempotent. Merely accepting the header is insufficient. - Mutable resources expose a revision and ETag. Conditional writes accept
If-Match; stale writes returnrevision_conflict. - The capability ledger states credential families, scope, risk, audit, and rate-limit policy. Plugin requests use the stricter surface profile even when the resource DTO and service are shared with a user/PAT request.
- Audit requirements use an explicit lifecycle (
plannedorenforced). The migrated operations remainplanneduntil a durable audit sink is wired; the ledger does not imply that a boolean marker performs an audit write.
Rollout ledger
The migrated slice is Issue read/content update and Comment read/create. Context and Storage remain Plugin extensions; Hook and invocation delivery remain on the bridge. Projects, Members, Issue search/create/transition, Agents, Squads, Skills, Tasks/Runs, and Autopilots are subsequent vertical slices. Each slice adds its Public contract first, then explicitly opts the safe Plugin subset into the capability ledger.