Skip to content

AppSubjectDataSource has no scopeNote, so a fork tier source that returns only some of a subject's rows cannot say so #816

Description

@JohnD-EE

Core's export manifest can tell a data subject "this source returns only some of your rows, and why". A fork tier's source cannot.

SubjectDataSource in lib/privacy/export-sources.ts has an optional scopeNote, and exportUserData() carries it into ExportedSourceSummary, so it lands in the bundle's meta beside the row count. That is the manifest's defence against a silently short answer: a source that narrows is required to say so, in a field a reader knows to look for.

AppSubjectDataSource in lib/privacy/subject-source-registry.ts has model, section, disposition and description, and nothing else. AppSourceSummary mirrors that. So a tier source that deliberately returns a subset has nowhere structured to disclose it.

The case that hit it

Resparkable has shared group workspaces. Its groupContributions section returns, for each group the subject belongs to, only the rows the subject created. Every other member's rows are withheld, because they are other people's personal data. That is exactly the situation scopeNote exists for.

What Resparkable does meanwhile

It writes the narrowing into description:

description: `What you wrote in each group workspace, one entry per group. ${GROUP_CONTRIBUTIONS_SCOPE_NOTE}`,

That works, in that the words reach meta.app. But it mixes "what this is" with "what was left out", and a reader (human or tool) scanning for narrowed sources has no field to find. It is the silent-omission failure the core manifest was built to prevent, one tier down.

Ask

  1. Add scopeNote?: string to AppSubjectDataSource, with the same doc comment core's field has.
  2. Carry it into AppSourceSummary with the same conditional spread core already uses for its own sources (...(source.scopeNote ? { scopeNote: source.scopeNote } : {})).
  3. Optionally, reject an empty-after-trim scopeNote in registerAppSubjectSources() the way description is checked, so a blank one cannot pass as a disclosure.

Small, additive, and non-breaking: no existing registration changes shape.

When it lands, Resparkable moves the constant into scopeNote and shortens the description back to what the section is.

Filed from Resparkable (ask #47).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    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