Skip to content

feat: add per-resource authorship property with read and write-on-create (DEV-6662)#4157

Open
danielasubotic wants to merge 5 commits into
mainfrom
feature/dev-6662-per-resource-authorship
Open

feat: add per-resource authorship property with read and write-on-create (DEV-6662)#4157
danielasubotic wants to merge 5 commits into
mainfrom
feature/dev-6662-per-resource-authorship

Conversation

@danielasubotic

Copy link
Copy Markdown
Contributor

Fixes DEV-6662

Motivation

The resource-side legal-metadata feature needs per-resource authorship so a data record can credit its authors independently of the project default and of file-level authorship. This is api-2 of the roadmap (spec: dasch-specs 03-feat-legal-metadata-resource-side-plan.md §4.B). It follows api-1 (project-level fields, dsp-api#4156) and is deployed alongside it.

Summary

Adds a new built-in property knora-base:hasResourceAuthorship (a flat datatype property on the resource node) and the read and write-on-create paths for it. The heavier, no-precedent post-create edit endpoint is split into DEV-6669 (api-2b) so it gets a focused, design-first PR.

This split aligns with the frontend: app-3's create-form (set authorship at creation) needs only this PR; only its inline edit needs api-2b.

Key Changes

  • Ontology: knora-base:hasResourceAuthorship (subjectClassConstraint :Resource, minCardinality 0); KnoraBaseVersion 51→52 with a MigrateOnlyBuiltInGraphs plugin registered for v52 (built-in-graph reload, no data migration — also reloads api-1's knora-admin additions). Mirrored in OntologyConstants (KnoraBase + KnoraApiV2) and KnoraBaseToApiV2ComplexTransformationRules (datatype property, subjectType knora-api:Resource).
  • Read: resourceAuthorship on ReadResourceV2 + toJsonLD (emitted only when set); extracted in ConstructResponseUtilV2; and GetResourcePropertiesAndValuesQuery extended (CONSTRUCT + OPTIONAL WHERE) because it enumerates resource predicates rather than returning them all.
  • Write-on-create: parsed from the POST /v2/resources JSON-LD (ApiComplexV2JsonLdRequestParser), carried on CreateResourceV2, threaded to ResourceReadyToCreate, and written as one triple per author in ResourcesRepoLive (no triples when empty).
  • Docs: knora-base.md Resources section.

Challenges and Decisions

  • Version-bump convention. KnoraBaseVersion was already 51; the established pattern (see RepositoryUpdatePlan v51) is to bump and register a MigrateOnlyBuiltInGraphs plugin — not a custom data migration. Done for v52.
  • The resource GET query enumerates predicates. GetResourcePropertiesAndValuesQuery lists resource-node predicates explicitly, so a new predicate is not returned automatically — I added hasResourceAuthorship to both the CONSTRUCT template and an OPTIONAL WHERE pattern.
  • Edit endpoint split (DEV-6669): new request/response JSON-LD messages, a new SPARQL UPDATE builder, and responder wiring with no FileValue precedent — isolated for a design-first PR.

Gotchas

  • R2R fixture must be regenerated, not hand-edited. OntologyFormatsE2ESpec compares the served knora-api ontology to test_data/generated_test_data/ontologyR2RV2/knoraApiOntologyWithValueObjects.jsonld and rewrites it on diff. The new property changes that output, so the fixture must be regenerated by running that e2e spec against the stack (it can't be produced without it). This spec will be red in CI until the regenerated fixture is committed — hence draft.
  • A create-round-trip e2e test (create with/without authorship → GET reflects it) is a follow-up to add with the stack.
  • dsp-app regenerates its OpenAPI client after this + api-1 are on dev.

Test Plan

  • Unit: ApiComplexV2JsonLdRequestParserSpeccreateResourceRequestV2 populates resourceAuthorship from knora-api:hasResourceAuthorship and leaves it empty when absent.
  • webapi/compile and webapi/Test/compile green locally; sbt fmt applied.
  • Follow-ups (need the Docker stack): regenerate the R2R fixture; add the create-round-trip e2e; R7 reload rehearsal before stage.

🤖 Generated with Claude Code

…ate (DEV-6662)

Adds the built-in knora-base:hasResourceAuthorship property (data-side authorship on
the resource node), bumps the ontology version 51->52, and implements the read path
(resource GET serialises it) and write-on-create (POST /v2/resources persists it).
The post-create edit endpoint is split into DEV-6669 (api-2b).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@linear-code

linear-code Bot commented Jun 21, 2026

Copy link
Copy Markdown

DEV-6662

@danielasubotic

Copy link
Copy Markdown
Contributor Author

Related PRs — resource-side legal metadata (R5-SC-04 / DEV-6475)

This is one of three coordinated dsp-api PRs for the feature (project fields → #4156, per-resource authorship property → #4157, edit endpoint → #4158). Downstream consumer PRs:

The api PRs deploy together; dsp-app regenerates its OpenAPI client from the deployed api and dsp-tools calls the JSON API directly. For local end-to-end testing, all three dsp-api PRs are combined on the feature/legal-metadata-resource-side-integration branch (see the LOCAL_TESTING guide).

danielasubotic and others added 3 commits June 21, 2026 21:13
…ion (DEV-6662)

The /v2/resources create parser iterated all non-metadata predicates as value
properties; the new knora-base:hasResourceAuthorship literals were parsed as
values, causing a 500 (Jena ResourceRequiredException) on create. Add it to the
filtered (metadata) predicates — it is read separately via RootResource.resourceAuthorship.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…uthorship (DEV-6662)

The new per-resource authorship property (knora-api:hasResourceAuthorship)
changes generated output that several tests assert against. No production
code changes.

- GetResourcePropertiesAndValuesQuerySpec: add the hasResourceAuthorship triple
  (CONSTRUCT) and OPTIONAL (WHERE) to the 12 expected SPARQL queries.
- Ontology format fixtures: regenerate the ontology JSON-LD fixtures (knora-api
  + anything) that now carry the inherited hasResourceAuthorship cardinality and
  the property definition. The matching .ttl is regenerated too (and reordered
  by the Turtle serializer) so it stays isomorphic with the JSON-LD, as
  JsonLDUtilSpec asserts.
- ApiComplexV2JsonLdRequestParserSpec: compare resourceAuthorship as an unordered
  set. Authorship is a plain multi-valued datatype property whose order does not
  round-trip (no rdf:List, no ORDER BY on read), consistent with asset-side
  authorship.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@codecov

codecov Bot commented Jun 23, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 85.36585% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 85.96%. Comparing base (a978c50) to head (a33832b).

Files with missing lines Patch % Lines
...esponder/resourcemessages/ResourceMessagesV2.scala 62.50% 3 Missing ⚠️
...webapi/messages/util/ConstructResponseUtilV2.scala 66.66% 1 Missing ⚠️
...ice/resources/repo/service/ResourcesRepoLive.scala 88.88% 1 Missing ⚠️
...ore/triplestore/upgrade/RepositoryUpdatePlan.scala 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4157      +/-   ##
==========================================
- Coverage   85.98%   85.96%   -0.02%     
==========================================
  Files         538      539       +1     
  Lines       30571    30578       +7     
  Branches     3559     3558       -1     
==========================================
  Hits        26286    26286              
- Misses       4285     4292       +7     
Flag Coverage Δ
e2e 85.96% <85.36%> (-0.02%) ⬇️
integration 85.96% <85.36%> (-0.02%) ⬇️
unit 85.96% <85.36%> (-0.02%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

…resource (DEV-6475)

The resource read mapped persisted knora-base:hasResourceAuthorship values via
Authorship.unsafeFrom, so any value that fails Authorship validation (e.g.
written out-of-band by tools or imported data) threw and turned every GET of
that resource into a 500. Parse leniently with Authorship.from and drop invalid
values so the resource stays readable.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant