Skip to content

feat: CTDL-ASN registry import and CASE alignment - #8

Draft
jeff-grann wants to merge 4 commits into
1EdTech:mainfrom
jeff-grann:feat/ctdl-asn-import-and-alignment
Draft

feat: CTDL-ASN registry import and CASE alignment#8
jeff-grann wants to merge 4 commits into
1EdTech:mainfrom
jeff-grann:feat/ctdl-asn-import-and-alignment

Conversation

@jeff-grann

Copy link
Copy Markdown

Summary

Adds the ability to import a CTDL-ASN competency framework from a Credential Engine registry into OpenCASE, view it in the editor and on the canvas, and align local CASE items to imported registry competencies (and to external frameworks) — with the registry provenance preserved end to end in a CASE-compliant way.

Imported frameworks open read-only and can be forked into an editable derivative on demand; alignments and provenance survive full save/reload round-trips.

What's included

Backend (apps/opencase)

  • CredentialRegistryClient fetches a CTDL-ASN @graph. The default registry origin is configurable via CREDENTIAL_REGISTRY_BASE_URL; passing a full resource URL to import overrides it per request, so prod / sandbox / self-hosted registries work without reconfiguration.
  • CtdlAsnToCaseMapper maps ceasn:CompetencyFramework / ceasn:Competency graphs to a CASE CFPackage, recording provenance under a unified ext:opencase.source block on the CFDocument and every CFItem.
  • ImportFrameworkFromRegistry + PreviewRegistryFramework endpoints, wired through the management controller/routes and DI container.
  • The document index derives isModifiedFromSource / sourcePackageURI from ext:opencase; a save of a still-locked registry import is no longer force-marked "modified".

Editor (apps/editor)

  • Import-from-registry dialog + a read-only registry reference node.
  • Read-only / fork workflow: imported frameworks block content and structural edits (layout stays editable); a header Enable editing action forks with confirmation, rewriting each node's ext:opencase.sourcederivedFrom and flagging the document isModifiedFromSource.
  • Alignment associations to registry and external-framework reference nodes are emitted on export; reference nodes are persisted in the document extension and reconstructed on load, and alignment edges are re-linked to the reconstructed nodes by destination URI (so they survive reload).
  • CASE export correctness: a top-level item's isChildOf targets the CFDocument (not a bogus /CFItems/<docId> URI); a registry alignment's destination identifier is the CTID's UUID rather than a hash.

The ext:opencase extension contract

Provenance is recorded in a namespaced CASE extension (CASE 1.1 has no native CTID field):

"ext:opencase": {
  "source": {                     // faithfully-imported node
    "uri":      "https://credentialengineregistry.org/resources/ce-…",  // @id — authoritative
    "ctid":     "ce-…",           // convenience (derivable from uri)
    "registry": "https://credentialengineregistry.org",                 // disambiguates multi-registry
    "format":   "ctdl-asn"
  }
  // after fork, `source` becomes `derivedFrom` (same shape) and the document adds isModifiedFromSource: true
}

Alignment associations carry the target resource URL in destinationNodeURI.uri (mirrored in ext:opencase.ctdlDestinationUri / externalDestinationUri).

Testing

  • Editor: full Vitest suite green, including new regression tests — toOpenCaseFormat (destination URIs), externalAlignment (association emitted + node persisted), alignmentRelink (edges re-link on reload), and the fork/provenance round-trip.
  • Backend: mapper, CredentialRegistryClient base resolution, CreateFramework fork-index gating, and management controller tests pass.

Configuration / deployment

  • New env var CREDENTIAL_REGISTRY_BASE_URL (default https://credentialengineregistry.org), surfaced in docker-compose.yml and docs/env.example.
  • Backend changes require an image rebuild (docker-compose up --build).

🤖 Generated with Claude Code

jeff-grann and others added 3 commits August 6, 2026 12:02
Adds server-side import of a competency framework from a CTDL-ASN registry
resource into a CASE CFPackage, plus the supporting configuration.

- CredentialRegistryClient fetches the CTDL-ASN @graph. The default registry
  origin is configurable via CREDENTIAL_REGISTRY_BASE_URL; a full resource URL
  passed to import overrides it per request (enables prod/sandbox/self-hosted
  registries without reconfiguration).
- CtdlAsnToCaseMapper maps ceasn:CompetencyFramework / ceasn:Competency graphs
  to a CASE CFPackage, recording registry provenance under a unified
  ext:opencase.source block (uri / ctid / registry / format) on the CFDocument
  and every CFItem, and setting officialSourceURL + sourcePackageURI.
- ImportFrameworkFromRegistry and PreviewRegistryFramework endpoints, wired
  through the management controller/routes and DI container.
- The document index lifts isModifiedFromSource / sourcePackageURI from
  ext:opencase; CreateFramework no longer force-marks registry-managed
  frameworks modified on a layout-only save (it trusts the editor's explicit
  fork flag; legacy CASE-package imports keep the previous behaviour).
- docker-compose + docs/env.example expose CREDENTIAL_REGISTRY_BASE_URL.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…nal alignment

Data/mapping layer for importing registry frameworks and aligning CASE items to
external competencies, with round-trip integrity.

- Preserve registry provenance across the editor round-trip: carry ext:opencase
  on the CFDocument snapshot (normalize + snapshot type) and reconcile the
  nested vs flattened extension shapes on export so provenance survives saves.
- Unified provenance: ext:opencase.source on documents and items; forking an
  imported framework rewrites source -> derivedFrom (provenance.ts) and the
  reducer's framework/enableEditing action applies it across all nodes.
- Alignment associations to BOTH registry and external-framework reference
  nodes are emitted on export (previously external edges were dropped); the
  reference nodes are persisted in the CFDocument extension and reconstructed on
  load, and alignment edges are re-linked to the reconstructed nodes by
  destination URI (fixes edges/associations being lost across a reload).
- Official-format (toOpenCaseFormat) URI fixes: a top-level item's isChildOf now
  targets the CFDocument (not a bogus /CFItems/<docId> URI), and a registry
  alignment's destination identifier is the CTID's UUID rather than a hash of
  the "ce-" string.
- Tests: toOpenCaseFormat (destination URIs), externalAlignment (association
  emitted + node persisted), alignmentRelink (edges re-link on reload).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Import-from-registry dialog and a read-only registry reference node type,
  wired into the home screen, app, and canvas (floating add menu).
- Imported registry frameworks open read-only: content edits and structural
  changes (add/remove items and associations) are blocked while layout changes
  stay allowed, enforced centrally in EditorContext. A header "Enable editing"
  action forks the framework after confirmation, recording derivation.
- Node properties panel shows registry provenance (CTID / CTDL URI / source
  registry) read-only, and the header/home reflect Imported vs Forked state.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@jeff-grann
jeff-grann marked this pull request as draft August 6, 2026 17:38
Walkthrough for importing a CTDL-ASN framework from a Credential Engine
registry, aligning CASE items to registry/external competencies, and the
read-only/fork workflow — with expected results at each step.

Co-Authored-By: Claude Opus 4.8 <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