Digital Services Act

Record-builders for the operator workflows the EU Digital Services Act (Regulation (EU) 2022/2065) requires an online intermediary or platform to keep on file. Three dated, frozen attestation records cover the regulation's core content-governance loop:

- noticeAndAction (Art. 16) records a notice a third party submits against a piece of content and computes the window inside which the provider must act on it. - statementOfReasons (Art. 17) records the moderation decision taken on a piece of content, its legal or contractual ground, the facts relied on, whether it was automated, and the redress routes offered to the affected recipient. - transparencyReport (Art. 15 / Art. 24(3)) aggregates the period counts a provider must publish — notices received, actions taken, automated decisions, appeals — into a report record with the next due date.

The builders follow the operator-feeds-metadata pattern: the operator supplies the facts and each function returns a frozen, timestamped record that composes into the operator's own retention / audit / export sink. None of them persist to the framework or touch the network. A best-effort dsa.* audit event fires when an audit sink is wired. They map to the dsa compliance posture, which cascades ML-DSA-87 audit-chain signing and a TLS 1.3 floor.

b.dsa.noticeAndAction(opts) #

stable0.15.8dsa
{
  contentId:       string,   // required — the content the notice targets
  noticeType:      string,   // required — illegal-content | terms-violation | ip-infringement | other
  reason:          string,   // required — the notice's substantiation (Art. 16(2)(a))
  submittedAt:     number,   // required — epoch ms the notice was submitted
  submitterType:   string,   // required — individual | trusted-flagger | authority | rights-holder | other
  noticeId:        string,   // optional — operator notice id; defaults to "dsa-notice-"
  actionWindowMs:  number,   // optional — SLA window; default 24h (Art. 16(6) "timely")
}

Record an Art. 16 notice-and-action notice and compute the window inside which the provider must act on it. The operator supplies the notice facts — the content it targets, the alleged category, the substantiating reason, when it was submitted, and who submitted it — and noticeAndAction validates the shape, stamps recordedAt, derives actionDueBy from the submission time plus the action window, and flags whether acting on the notice will require an Art. 17 statement of reasons (true for illegal-content / IP notices). The returned record is frozen and is NOT framework-persisted — compose it into your retention / audit / export sink. A best-effort dsa.notice.recorded audit event fires when an audit sink is wired.

var n = b.dsa.noticeAndAction({
  contentId:     "post-9931",
  noticeType:    "illegal-content",
  reason:        "Depicts a sale prohibited under national law.",
  submittedAt:   Date.now(),
  submitterType: "trusted-flagger",
});
// → { noticeId, contentId, noticeType, status: "recorded",
//     recordedAt, actionDueBy, statementOfReasonsRequired: true }

b.dsa.statementOfReasons(opts) #

stable0.15.8dsa
{
  contentId:          string,    // required — the content the decision concerns
  decision:           string,    // required — content-removed | content-disabled | ... | no-action
  facts:              string,    // required — the facts and circumstances relied on (Art. 17(3)(c))
  automated:          boolean,   // required — was the decision taken by automated means (Art. 17(3)(c))
  redressOptions:     string[],  // required — internal-complaint | out-of-court-settlement | judicial-redress
  legalGround:        string,    // one-of-two — the legal ground when the decision rests on illegality (Art. 17(3)(d))
  contractualGround:  string,    // one-of-two — the T&C clause when the decision rests on the contract (Art. 17(3)(e))
  sorId:              string,    // optional — operator id; defaults to "dsa-sor-"
  noticeId:           string,    // optional — the Art. 16 notice this answers, if any
  territorialScope:   string,    // optional — geographic scope of the restriction (Art. 17(3)(b))
}

Record an Art. 17 statement of reasons for a content-moderation decision. Whenever a provider restricts content (or a recipient's account) it must give the affected recipient a clear, specific statement of reasons; this builder records that statement as a frozen dated record. The operator supplies the decision, the legal ground (Art. 17(3)(d)) or the contractual ground (Art. 17(3)(e)) it rests on, the facts relied on (Art. 17(3)(c)), whether the decision was taken by automated means (Art. 17(3)(c)), and the redress routes offered (Art. 17(3)(f)). Exactly one of legalGround / contractualGround is required so the ground is never left implicit. The returned record is frozen and is NOT framework-persisted — also submit it to the Commission's DSA Transparency Database per Art. 24(5) from your own pipeline. A best-effort dsa.sor.recorded audit event fires when an audit sink is wired.

var s = b.dsa.statementOfReasons({
  contentId:      "post-9931",
  decision:       "content-removed",
  legalGround:    "National law prohibiting the depicted sale.",
  facts:          "Listing offered a prohibited item for sale.",
  automated:      false,
  redressOptions: ["internal-complaint", "judicial-redress"],
});
// → { sorId, contentId, decision, recordedAt, groundType, automated, ... }

b.dsa.transparencyReport(opts) #

stable0.15.8dsa
{
  period:    object,   // required — { from: number, to: number } epoch-ms window (from < to)
  metrics:   object,   // optional — { : number } period counts; see b.dsa.listTransparencyMetrics()
  reportId:  string,   // optional — operator id; defaults to "dsa-transparency-"
  service:   string,   // optional — the service the report covers
}

Build an Art. 15 (all intermediary services) / Art. 24(3) (online platforms) transparency report. The operator supplies the reporting period and the period counts — notices received, actions taken, automated decisions, appeals, and so on — and transparencyReport validates the shape, normalises every metric to a non-negative integer (omitted metrics default to 0 so a partial report still has a complete, comparable shape), stamps generatedAt, and computes nextReportDueBy one year after the period end (Art. 15(1) "at least once a year"). The returned report is frozen and is NOT framework-persisted — publish it from your own pipeline. A best-effort dsa.transparency_report.generated audit event fires when an audit sink is wired.

var r = b.dsa.transparencyReport({
  period:  { from: Date.UTC(2025, 0, 1), to: Date.UTC(2025, 11, 31) },
  metrics: { noticesReceived: 1200, actionsTaken: 940, automatedDecisions: 610, appeals: 75 },
});
// → { reportId, period, metrics: {...all 9 normalised...}, generatedAt, nextReportDueBy }

b.dsa.listTransparencyMetrics() #

stable0.15.8

Return the frozen list of metric field names a transparencyReport aggregates — each maps to an Art. 15 / Art. 24 reporting obligation. Use it to render a data-entry form or to enumerate the counts the report normalises.

b.dsa.listTransparencyMetrics();
// → ["noticesReceived", "actionsTaken", "automatedDecisions", ...]

Last updated 2026-08-08T16:39:49.652Z by seeder.