Repository navigation
Description
Motivation
A server can serve a static maintenance notice even when its application cannot send announcements. An outbound delivery may then receive a response with a Link header pointing to that notice. Without FEP-f799 HTTP discovery, Fedify can verify notices delivered as activities but cannot learn about this fetched-only publication path.
Add discovery as an optional source for the existing receiver. Fetching an advertised URL must not itself authorize a hold or alter the response that triggered discovery.
Proposed API and use
Extend setDeliverySuspension() with a linkDiscovery option. Keep actual response observation internal; expose a bounded pure parser for diagnostic tools.
interface DeliverySuspensionLinkDiscoveryOptions {
maxHeaderBytes?: number;
maxLinksPerResponse?: number;
minAttemptInterval?: Temporal.DurationLike;
responderBudget?: { fetches: number; per: Temporal.DurationLike };
targetBudget?: { fetches: number; per: Temporal.DurationLike };
maxPendingJobs?: number;
maxConcurrentFetches?: number;
filter?: (link: DeliverySuspensionLink, provenance: LinkProvenance) => boolean;
}
function parseDeliverySuspensionLinks(
headers: Headers,
options: { contextUrl: string; maxHeaderBytes?: number; maxLinks?: number },
): { links: readonly DeliverySuspensionLink[]; skipped: readonly { reason: string }[] };A link includes its resolved notice URL, raw target and advisory media type. Provenance retains the logical response URL, original inbox, actual request sequence, independent redirect/negotiation indices, response status and final-response flag.
const receiver = federation.setDeliverySuspension({
mode: "apply",
policy: { profile: "baseline-v1" },
linkDiscovery: { maxLinksPerResponse: 4, maxConcurrentFetches: 2 },
});
// A separate diagnostic tool can inspect the syntax without granting a hold.
const parsed = parseDeliverySuspensionLinks(headers, {
contextUrl: "https://remote.example/inbox",
maxLinks: 4,
});
console.log(parsed.links);The configuration and helper are proposed additions. The normal owned runner or bounded receiver.runOnce(ctx) processes discovered hints through the same authenticated admission used by activities and pending cancellations.
Processing and decisions
Parse each HTTP response synchronously and push candidate links into a bounded local buffer. Do not await KV, queue or remote I/O in the delivery response path, or leave an unowned promise running after the request. Buffered means local acceptance, not durable enqueue success. Respect strict task-queue routing and explicit runner/fallback choices. Hint loss never creates a hold or deletes an accepted fact.
Resolve relative targets against the logical response context. Require the original resolved link URL to match the fetched object's ID; comparing the final CDN redirect URL instead would reject valid canonical-to-CDN hosting. Respect anchor context and parse quoted commas/parameters instead of splitting the header on commas. RFC 8288 §2.1.2 specifies case-insensitive extension relation comparison; do not apply that rule to object IDs or capability hrefs.
Limit both the responding origin and target origin, header size, jobs, URL retry frequency and fetch concurrency. Unless a distributed budget is implemented, document these as instance-level protection. Existing default document and WebFinger loaders already bound response bodies; smaller per-operation or aggregate limits need real implementation and must not be described as existing defaults.
Use the internal returned-session fetch seam without importing federation code into the signature layer. Parser/filter/observer errors must not change HTTP results, Retry-After or the existing failure classifier. The filter may suppress a candidate but cannot confer trust. A public generic Response admission hook and a second independent polling engine were rejected: the receiver already owns authentication, freshness and revalidation of accepted notices, including when this option is off.
Shipping criteria and docs
Test 202 Accepted/503 Service Unavailable links, canonical-to-CDN redirects, foreign anchors, quoted commas, repeated parameters, relation case, excessive headers, different responder/target budgets, signature retry provenance, lost hints and strict queue routing. Ensure a failed discovery fetch does not fabricate a delivery failure or hold.
Add discovery/abuse/runner examples to docs/manual/delivery-suspension.md and relevant send.md, tasks.md and diagnostic guidance. Revise JSDoc, framework/inbox skill guidance where it describes discovery, and the core fragment. This child adds a complete new source; it does not supply baseline receiver revalidation that should already ship.
Metadata
Metadata
Assignees
Labels
Type
Fields
Priority
Effort
Activity