Skip to content

The /share-links dispatcher domain emits data AND a legacy link/links beside it — a producer-side shim that outlived its readers #4038

Description

@os-zhuang

Found while sweeping consumers for #3983. Not fixed there because deleting it needs a cloud-side check that is out of that PR's scope (Prime Directive #10).

The shim

packages/runtime/src/domains/share-links.ts answers create and list with the payload under two keys:

// POST /share-links → create
return { handled: true, response: { status: 201, body: { success: true, data: link, link } } };

// GET /share-links?object&recordId → list
return { handled: true, response: { status: 200, body: { success: true, data: links, links } } };

Note these bypass deps.success() — the domain's other three routes (revoke, resolve, messages) go through it and emit a clean { success: true, data }. Only these two hand-build a body, and the only reason to is the duplicate key.

That is a producer-side compatibility shim: the legacy link / links keys are there for readers written before the envelope existed. Prime Directive #12 is about deleting consumer-side sniffing by fixing the producer; this is the mirror image — a producer emitting two dialects at once so consumers never have to choose.

Why it can go now (and why not yet)

#3983 removes the reason it exists. Before that PR, the sharing plugin's routes answered bare { link } / { links } while this domain answered enveloped, so every consumer had to tolerate both:

// objectui packages/components/src/share/ShareDialog.tsx
setLinks(body.links ?? body.data ?? []);
const newLink = created.link ?? created.data;

That ?? is reading the plugin's shape first and this domain's second. Once #3983 lands, both surfaces answer data, the fallback is dead code, and the duplicate key has no reader left in either repo.

What still needs checking before deletion: this domain is the designed primary surface for cloud's per-environment kernels (registerShareLinkRoutes: false, per the #2462 step-① note in the file header). Anything in cloud reading body.link / body.links off these two routes would break. I can't see that repo from this session, so the sweep has to happen there.

Suggested shape of the fix

  1. Sweep cloud for body.link / body.links reads against POST|GET /share-links.
  2. Drop the duplicate keys and route both through deps.success(...) like the domain's other three routes — which also removes the two hand-built bodies.
  3. Delete the now-dead ?? body.data / ?? created.data fallbacks in objectui's ShareDialog (they become unreachable, and leaving them implies a shape that no longer exists).
  4. Add the two routes to the dispatcher's envelope coverage so a hand-built body can't come back.

Step 3 is the part worth doing even if 1–2 are deferred: a tolerance kept after its reason is gone reads as "both shapes are still live" to the next person, which is how #3833 happened.

Scope note

scripts/check-route-envelope.mjs does not cover this file — it scans route modules that write via res.json(...), and the dispatcher domains return { status, body } objects for a central sender instead. So this drift is invisible to that guard by construction. Whether the guard should grow a second mode for the domain handlers is a bigger question than this issue; worth raising separately if the dispatcher turns out to have more of these.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions