Files
multica/server/pkg/db/generated
Bohan Jiangandmultica-agent 1296bb45e0 MUL-7051 fix(subscribers): stop an armed autopilot from subscribing its trigger's creator (#8031)
* fix(subscribers): stop an armed autopilot from subscribing its trigger's creator

An autopilot fires on its schedule, its agent files issues, and the member who
armed the trigger is auto-subscribed to every one of them.

The delegated-subscriber rule (MUL-5483) subscribes the human an agent-created
issue exists on behalf of, and it tested that by asking whether the origin run
carries an originator. That was sound when it was written: direct_human was the
only attribution root that left an originator behind, so "this run carries a
human" and "a human asked for this work" were the same statement.

MUL-6951 separated them. An armed schedule/webhook trigger now runs with its
creator's authorization (trigger_owner), and attribution COPIES that human down
every agent hop, so the rule started reading an automation's authorization as a
request. attribution.DelegatedSubscriber already documents this exact outcome as
one it must not produce — the origin_type='autopilot' exclusion says the
autopilot's own subscriber template, not whoever armed the trigger, is the
audience for its issues. The regression arrives one hop below that exclusion,
where the issue's origin is an ordinary agent_create.

The rule now asks what it means: did this chain BEGIN with a member acting. The
originator alone cannot answer that below the first hop, because a hop relabels
its own originator_source to 'delegation' — so GetDelegatedSubscriptionFacts
walks delegated_from_task_id back to the run that actually resolved the human and
returns that root's label alongside the originator, in one workspace-scoped read
that replaces the previous single-task load. Accepting only direct_human makes it
a whitelist: the next root that resolves a human some other way stays silent here
until someone decides otherwise, instead of switching this rule on for a
population nobody chose.

No schema change and no change to attribution itself: originator, accountable and
every authorization decision are untouched. Only who gets subscribed moves.

Verification (real PostgreSQL 17): internal/attribution, cmd/server pass; the
four new tests fail against the unfixed rule, and the tenant-guard test fails
when the workspace predicate is removed from the new query. internal/handler and
internal/service each keep one pre-existing failure that reproduces identically
on a clean tree (source-context object-store cleanup), as do cmd/multica,
internal/cli, internal/daemon and internal/daemon/execenv.

Co-authored-by: multica-agent <[email protected]>

* test(subscribers): close the review gaps in the lineage walk's coverage

Addresses Elon's review on #8031.

The 32-hop stop is accepted as a product limit (Bohan's call), so it is now
written down as behaviour instead of contradicted by it. DelegatedSubscriber
claimed "No depth cap", which was true of WHO the human is — the originator is
copied onto every run — but not of proving the chain began with them, which is
the part that walks. The query comment called the cap cycle protection only. Both
now say what actually happens: past 32 hops the root is unproven and nobody is
subscribed. TestDelegatedSubscribe_LineageWalkStopsAt32Hops pins both sides, so
the limit cannot drift silently; moving it to 3 reddens the 32-hop case.

The tenant test claimed to cover every hop and covered one. An issue pointing
straight at a foreign run only exercises the anchor's predicate, so deleting the
recursive branch's workspace_id left it green. It is now two cases, and the added
one — a local run naming a foreign parent — fails with that predicate removed
while the original case still passes, which is exactly the blind spot.

The chain fixture builds through internal/testutil instead of hand-writing an
INSERT with a matching cleanup, per the repository's test convention.

No production behaviour changes: the rule, the walk and every existing assertion
are untouched.

Verification (real PostgreSQL 17): cmd/server, internal/attribution,
internal/service pass; both new tests were run against a deliberately broken
query and fail there. gofmt, go vet, git diff --check clean.

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: J <[email protected]>
2026-09-04 16:33:58 +08:00
..