Skip to content

refactor: write literal property values directly + decode both old and new shapes#604

Draft
HexaField wants to merge 4 commits into
devfrom
refactor/literal-channel-v-separation
Draft

refactor: write literal property values directly + decode both old and new shapes#604
HexaField wants to merge 4 commits into
devfrom
refactor/literal-channel-v-separation

Conversation

@HexaField
Copy link
Copy Markdown
Contributor

@HexaField HexaField commented Jun 4, 2026

Summary

Companion to coasys/ad4m#837. After that PR lands, the ad4m executor stops embedding signed-expression envelopes ({author, timestamp, data, proof}) in link targets when properties are written through the literal language — per-link author/timestamp/proof lives only on the RDF reifier going forward. This PR brings flux into line on both sides of that contract: the write helpers that put the envelope into the target in the first place, and the read sites that pulled values out of the envelope shape via .get().data.

Writes — stop embedding provenance in targets

Five flux call sites previously routed property values through client.expression.create(value, 'literal'). The executor's literal language signs the value into a literal:json:<envelope> URL, so the target carried {author, timestamp, data, proof} duplicating provenance the reifier already holds. After this PR every property target is encoded client-side as a deterministic plain literal:string: / :number: / :boolean: / :json: URL via Literal.from(value).toUrl(). No round-trip to the executor, no embedded provenance, no envelope.

File Sites
packages/utils/src/createNeighbourhoodMeta.ts neighbourhood name, createdAt, description
packages/utils/src/linkHelpers.ts (createLiteralLinks) generic property-link helper used by createProfile, updateProfile
packages/utils/src/linkHelpers.ts (createLiteralObject) parent + children helper used by createAgentWebLink

createLiteralObject gains a useful side effect: the deterministic parent URL doubles as a stable entity identity, so two calls with the same parent.target value resolve to the same IRI — which is what callers like createAgentWebLink actually want (same URL → same WebLink entity).

grep -rn "expression\.create\([^)]*['\"]literal['\"]\)" against packages/ returns no hits after this PR. The only remaining expression.create("…", "literal") callers across the ecosystem are dapp entanglement proofs and agent expressions in the ad4m repo, both of which intentionally produce addressable signed expressions (a separate concern from link-property storage).

Reads — handle both old and new target shapes

New unwrapLiteralValue(target) helper in @coasys/flux-utils that decodes literal: URLs and returns the inner value:

  • Plain literal → returns the decoded value directly.
  • Signed-expression envelope (legacy data on disk before the ad4m migration runs, plus any explicit expression.create(value, "literal") URL that callers feed in) → returns the inner .data.
  • Anything else (non-literal URL, undecodable) → returns undefined; call sites substitute the raw target.

Updated four reader sites that previously assumed the envelope shape:

File Was
packages/utils/src/linkHelpers.ts (mapLiteralLinks) three-prong startsWith dispatch with .get().data on the json: branch
packages/utils/src/getNeighbourhoodMeta.ts (getMetaFromLinks) .get().data on NAME / DESCRIPTION / CREATED_AT predicates
packages/utils/src/prologHelpers.ts (resolveExp inside model property resolution) .get().data on literal: URLs
packages/api/src/getAgentWebLinks.ts .get().data on weblink parent target

Plus packages/api/src/utils/parseLit.test.ts flipped from asserting .data extraction to asserting JSON.stringify(obj) to match parseLit's new behaviour in ad4m#837 (envelope semantics live in unwrapLiteralValue now, not in parseLit).

Test plan

  • pnpm exec vitest run packages/api/src/utils/unwrapLiteralValue (7/7) + parseLit (6/7 locally against the published ad4m, 7/7 expected in CI against the linked branch)
  • pnpm exec tsc --noEmit -p packages/utils/tsconfig.json clean for changed files
  • pnpm exec tsc --noEmit -p packages/api/tsconfig.json clean for changed files
  • Full CI green on this PR (resolves the parseLit assertion via the same-name ad4m branch)
  • Manual smoke: create a community, verify name/description round-trip through createNeighbourhoodMeta + getMetaFromLinks
  • Manual smoke: create a WebLink, verify two calls with the same URL produce one entity (deterministic identity check)

Cross-repo coupling

Flux CI resolves the same-name refactor/literal-channel-v-separation branch of @coasys/ad4m and tests against that build, not the currently-published version. The two PRs ship as one logical change.

After the ad4m executor stops emitting signed-expression envelopes for
literal-language property writes, link targets storing string/number/
boolean values come back from Literal.fromUrl().get() as the raw value
rather than as an envelope object with a .data field. Existing
.get().data sites would start returning undefined.

Introduce unwrapLiteralValue in flux-utils which decodes literal: URLs
and returns the inner value for both plain and signed-envelope shapes.
Update the five sites in flux-utils + flux-api that previously assumed
the envelope shape.
@netlify
Copy link
Copy Markdown

netlify Bot commented Jun 4, 2026

Deploy Preview for fluxsocial-dev ready!

Name Link
🔨 Latest commit f997812
🔍 Latest deploy log https://app.netlify.com/projects/fluxsocial-dev/deploys/6a20c7c82b263f000850e433
😎 Deploy Preview https://deploy-preview-604--fluxsocial-dev.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 4, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7f823a06-dd91-4c87-a035-8a3dec70df36

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/literal-channel-v-separation

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

HexaField added 3 commits June 4, 2026 10:27
Cross-repo branch linking means flux CI runs the same-name ad4m branch
of @coasys/ad4m, which drops the .data extraction from parseLit. Caller-
visible behaviour: literal:json: objects round-trip as JSON.stringify,
leaving envelope-vs-plain shape decisions to unwrapLiteralValue.
createNeighbourhoodMeta, createLiteralLinks, and createLiteralObject
previously routed property values through client.expression.create(value,
'literal'), which signs the value into a literal:json:<envelope> URI on
the executor — embedding author/timestamp/proof in the target IRI and
duplicating provenance that already lives on the link reifier.

Encode the value client-side with Literal.from(value).toUrl() instead.
Targets become deterministic plain literal URIs; the reifier remains the
single source of truth for who wrote the link and when.

createLiteralObject now uses the deterministic parent URL as a stable
entity identity — two calls with the same parent.target value resolve
to the same parent IRI, which is the intended semantics for value-keyed
entities like web links.
@HexaField HexaField changed the title refactor: adapt to ad4m literal-channel-V property reads refactor: literal targets are values, not signed expressions Jun 4, 2026
@HexaField HexaField changed the title refactor: literal targets are values, not signed expressions refactor: write literal property values directly + decode both old and new shapes Jun 4, 2026
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