Problem
Source RDI (Research Data Infrastructure) context is today outside the ARC payload:
- API request body (
CreateArcRequest.rdi) or harvest document
- CouchDB envelope (
ArcDocument.rdi)
- Celery task payload (
ArcSyncTask.rdi)
ArcStore.create_or_update(..., rdi=rdi) for GitLab project topics
The ARC itself only carries investigation metadata (identifier, name/title, description). When an ARC leaves the middleware (Git clone, export), it does not record which RDI it belongs to, nor infrastructure description or URL.
Goal
Embed source RDI inside the ARC in a way that:
- survives the middleware Git sync path (
ARC.from_rocrate_json_string → arc.Write())
- is standards-aligned (ISA / RO-Crate), not a proprietary sidecar format
- carries at minimum: RDI identifier, description, and canonical URL
- allows the middleware to remain the security authority for which RDI an ingest is allowed
Preferred approach: ISA Investigation Comments
Why not RO-Crate Organization / publisher?
RO-Crate contextual entities (Organization + isPartOf / publisher) are semantically correct, and RoCratePayload preserves extra @graph nodes in CouchDB.
However, arctrl drops them on round-trip:
ARC.from_rocrate_json_string(json_with_Organization) → ToROCrateJsonString()
→ publisher / isPartOf / Organization nodes are gone
The Git sync path uses arctrl for writing the scaffold, so RO-Crate-only enrichment would not survive Git push.
Why not proprietary sidecar files?
arc.Write() produces the ISA scaffold (isa.investigation.xlsx, studies/, …) and does not emit ro-crate-metadata.json at the Git repo root.
The middleware Git sync wipes the repo (except .git) before each arc.Write(). Arbitrary files such as fairagro-rdi.json would be deleted unless they are part of the ARC object.
Sidecar files would also be invisible to standard ARC tooling.
Why not ISA Publication or Publisher?
The ISA Abstract Model Investigation has Publications (scholarly articles), Contacts (people with Affiliation as free text), but no Publisher field for hosting infrastructure.
Comment[Funder] (ISA-Tab Scientific Data extension) targets funding agencies, not RDI hosting — semantically wrong for our use case.
ISA Comment[<name>] — the sweet spot
ISA-XLSX allows arbitrary investigation-level comments. arctrl supports them via Comment.create(name, value):
from arctrl import Comment
inv.Comments.append(Comment.create("RDI", "edaphobase"))
inv.Comments.append(Comment.create("RDI Description", "Edaphobase soil biodiversity database"))
inv.Comments.append(Comment.create("RDI URL", "https://www.edaphobase.org"))
Verified behaviour:
| Layer |
Result |
| RO-Crate |
@type: Comment nodes linked from root Dataset via comment |
| ISA-XLSX |
Comment[RDI] | edaphobase row in isa.investigation.xlsx |
| arctrl round-trip |
Preserved (unlike Organization nodes) |
Git sync (arc.Write) |
Written into investigation workbook |
Proposed comment names (to standardise)
| Comment name |
Content |
Example |
RDI |
RDI identifier (must match authorized ingest RDI) |
edaphobase |
RDI Description |
Human-readable infrastructure summary |
Edaphobase soil biodiversity database |
RDI URL |
Canonical infrastructure URL |
https://www.edaphobase.org |
Names are open for bikeshedding; consider a short FAIRagro convention doc once agreed.
Authority model (recommended: middleware enrich + validate)
| Source |
Role |
API rdi / harvest document rdi |
Authoritative for auth, arc_id, CouchDB envelope |
| Deployment RDI registry (config) |
Source for description + URL |
| ISA Comments in ARC |
Mirror for portability; optional client pre-fill |
Rules to define:
- On ingest, middleware injects or updates the three
Comment[...] fields from the authorized RDI + registry.
- If the client already supplied RDI comments, they must match the authorized RDI (and registry values, or middleware overwrites) — otherwise
422.
- Harvest path (
POST /v3/harvests/{harvest_id}/arcs): RDI from harvest document; enrichment same as standalone upload.
arc_id = sha256(f"{identifier}:{rdi}") unchanged; RDI comment must stay consistent with envelope rdi.
Out of scope / explicitly rejected
- Proprietary sidecar JSON/YAML in the ARC scaffold
- RO-Crate
Organization as the only carrier (until arctrl preserves it on round-trip)
- Treating ARC-embedded RDI as the security boundary (certificate allowlist remains external)
Implementation phases
Phase 1 — Design & config
Phase 2 — Ingest enrichment
Phase 3 — Read path & ArcStore decoupling
Phase 4 — Client / API docs
Acceptance criteria
Technical notes
RoCratePayload already allows extra @graph nodes; Comments are also representable as RO-Crate Comment type after arctrl serialization.
GitRepo._create_or_update wipes non-.git files before arc.Write() — any solution must go through the ARC object, not loose files.
- Today
known_rdis is identifier-only (middleware/api/src/middleware/api/config.py); description/URL need a registry.
- Background: refactoring
git_metadata off ArcStore exposed rdi as the last middleware-only context not on the arctrl ARC object.
Related code
middleware/api/src/middleware/api/business_logic/arc_manager.py
middleware/api/src/middleware/api/document_store/arc_document.py
middleware/api/src/middleware/api/arc_store/remote_git_provider.py (git_project_metadata_from_arc)
middleware/shared/src/middleware/shared/api_models/common/rocrate.py
middleware/api/spec/arc-upload/spec.md, harvest-arc-upload/spec.md
References
Problem
Source RDI (Research Data Infrastructure) context is today outside the ARC payload:
CreateArcRequest.rdi) or harvest documentArcDocument.rdi)ArcSyncTask.rdi)ArcStore.create_or_update(..., rdi=rdi)for GitLab project topicsThe ARC itself only carries investigation metadata (
identifier,name/title,description). When an ARC leaves the middleware (Git clone, export), it does not record which RDI it belongs to, nor infrastructure description or URL.Goal
Embed source RDI inside the ARC in a way that:
ARC.from_rocrate_json_string→arc.Write())Preferred approach: ISA Investigation Comments
Why not RO-Crate
Organization/publisher?RO-Crate contextual entities (
Organization+isPartOf/publisher) are semantically correct, andRoCratePayloadpreserves extra@graphnodes in CouchDB.However, arctrl drops them on round-trip:
The Git sync path uses arctrl for writing the scaffold, so RO-Crate-only enrichment would not survive Git push.
Why not proprietary sidecar files?
arc.Write()produces the ISA scaffold (isa.investigation.xlsx,studies/, …) and does not emitro-crate-metadata.jsonat the Git repo root.The middleware Git sync wipes the repo (except
.git) before eacharc.Write(). Arbitrary files such asfairagro-rdi.jsonwould be deleted unless they are part of theARCobject.Sidecar files would also be invisible to standard ARC tooling.
Why not ISA
PublicationorPublisher?The ISA Abstract Model Investigation has
Publications(scholarly articles),Contacts(people withAffiliationas free text), but no Publisher field for hosting infrastructure.Comment[Funder](ISA-Tab Scientific Data extension) targets funding agencies, not RDI hosting — semantically wrong for our use case.ISA
Comment[<name>]— the sweet spotISA-XLSX allows arbitrary investigation-level comments. arctrl supports them via
Comment.create(name, value):Verified behaviour:
@type: Commentnodes linked from root Dataset viacommentComment[RDI] | edaphobaserow inisa.investigation.xlsxOrganizationnodes)arc.Write)Proposed comment names (to standardise)
RDIedaphobaseRDI DescriptionEdaphobase soil biodiversity databaseRDI URLhttps://www.edaphobase.orgNames are open for bikeshedding; consider a short FAIRagro convention doc once agreed.
Authority model (recommended: middleware enrich + validate)
rdi/ harvest documentrdiarc_id, CouchDB envelopeRules to define:
Comment[...]fields from the authorized RDI + registry.422.POST /v3/harvests/{harvest_id}/arcs): RDI from harvest document; enrichment same as standalone upload.arc_id = sha256(f"{identifier}:{rdi}")unchanged; RDI comment must stay consistent with enveloperdi.Out of scope / explicitly rejected
Organizationas the only carrier (until arctrl preserves it on round-trip)Implementation phases
Phase 1 — Design & config
middleware/api/spec/)known_rdis: list[str](identifier + description + url)Phase 2 — Ingest enrichment
arc_contentdict or via arctrl afterARC.from_rocrate_json_stringrdiPhase 3 — Read path & ArcStore decoupling
git_project_metadata_from_arc(fallback tordiparameter during migration)rdiargument fromArcStore.create_or_updateonce reliableComment[RDI]valuePhase 4 — Client / API docs
rdiinCreateArcRequestremains required for authorization (even when Comments are present)Acceptance criteria
arc_contentcontains standardized RDI Comments after ingestisa.investigation.xlsxcontainsComment[RDI*]rows after syncCommententitiesarc_idTechnical notes
RoCratePayloadalready allows extra@graphnodes; Comments are also representable as RO-CrateCommenttype after arctrl serialization.GitRepo._create_or_updatewipes non-.gitfiles beforearc.Write()— any solution must go through theARCobject, not loose files.known_rdisis identifier-only (middleware/api/src/middleware/api/config.py); description/URL need a registry.git_metadataoffArcStoreexposedrdias the last middleware-only context not on the arctrlARCobject.Related code
middleware/api/src/middleware/api/business_logic/arc_manager.pymiddleware/api/src/middleware/api/document_store/arc_document.pymiddleware/api/src/middleware/api/arc_store/remote_git_provider.py(git_project_metadata_from_arc)middleware/shared/src/middleware/shared/api_models/common/rocrate.pymiddleware/api/spec/arc-upload/spec.md,harvest-arc-upload/spec.mdReferences
.agents/skills/arctrl/SKILL.md