Skip to content

Feat/w3ds file uri#965

Merged
coodos merged 12 commits into
mainfrom
feat/w3ds-file-uri
May 18, 2026
Merged

Feat/w3ds file uri#965
coodos merged 12 commits into
mainfrom
feat/w3ds-file-uri

Conversation

@coodos
Copy link
Copy Markdown
Contributor

@coodos coodos commented May 18, 2026

Description of change

adds file URI scheme and fixes mappings

Issue Number

closes #964

Type of change

  • New (a change which implements a new feature)

How the change has been tested

Change checklist

  • I have ensured that the CI Checks pass locally
  • I have removed any unnecessary logic
  • My code is well documented
  • I have signed my commits
  • My code follows the pattern of the application
  • I have self reviewed my code

Summary by CodeRabbit

  • New Features

    • Added file upload capability with GraphQL mutation
    • Added file dereferencing endpoint for retrieving uploaded files
    • Enabled file integration in web3 mappings using __file() directive
    • Added support for object storage (S3-compatible infrastructure)
  • Documentation

    • Added documentation for file URI scheme and handling
    • Added mapping rules documentation for file support
  • Tests

    • Added unit tests for file URI utilities
  • Chores

    • Added S3 SDK dependency for object storage support

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 18, 2026

Warning

Rate limit exceeded

@coodos has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 35 minutes and 26 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2f8e46f9-0744-4e8a-8465-458e47243aa1

📥 Commits

Reviewing files that changed from the base of the PR and between 1ac9ae8 and 597dfc8.

📒 Files selected for processing (30)
  • infrastructure/evault-core/src/core/http/server.ts
  • infrastructure/evault-core/src/core/protocol/graphql-server.ts
  • infrastructure/evault-core/src/core/utils/w3ds-uri.ts
  • infrastructure/evault-core/src/services/StorageService.ts
  • infrastructure/web3-adapter/MAPPING_RULES.md
  • infrastructure/web3-adapter/W3DS_URI.md
  • infrastructure/web3-adapter/src/mapper/file-directive.test.ts
  • infrastructure/web3-adapter/src/mapper/mapper.ts
  • infrastructure/web3-adapter/src/w3ds/resolver.ts
  • infrastructure/web3-adapter/src/w3ds/uri.test.ts
  • platforms/blabsy/api/src/web3adapter/mappings/message.mapping.json
  • platforms/blabsy/api/src/web3adapter/mappings/social-media-post.mapping.json
  • platforms/blabsy/api/src/web3adapter/mappings/user.mapping.json
  • platforms/cerberus/client/src/web3adapter/mappings/user.mapping.json
  • platforms/dreamsync/api/src/web3adapter/mappings/group.mapping.json
  • platforms/dreamsync/api/src/web3adapter/mappings/user.mapping.json
  • platforms/ecurrency/api/src/web3adapter/mappings/group.mapping.json
  • platforms/ecurrency/api/src/web3adapter/mappings/user.mapping.json
  • platforms/ereputation/api/src/web3adapter/mappings/group.mapping.json
  • platforms/ereputation/api/src/web3adapter/mappings/user.mapping.json
  • platforms/esigner/api/src/web3adapter/mappings/group.mapping.json
  • platforms/esigner/api/src/web3adapter/mappings/user.mapping.json
  • platforms/evoting/api/src/web3adapter/mappings/group.mapping.json
  • platforms/evoting/api/src/web3adapter/mappings/user.mapping.json
  • platforms/file-manager/api/src/web3adapter/mappings/group.mapping.json
  • platforms/file-manager/api/src/web3adapter/mappings/user.mapping.json
  • platforms/group-charter-manager/api/src/web3adapter/mappings/user.mapping.json
  • platforms/pictique/api/src/web3adapter/mappings/comment.mapping.json
  • platforms/pictique/api/src/web3adapter/mappings/post.mapping.json
  • platforms/pictique/api/src/web3adapter/mappings/user.mapping.json
📝 Walkthrough

Walkthrough

This pull request implements a complete file URI referencing and dereferencing system via the w3ds://file URI scheme. It adds storage configuration, GraphQL upload/dereference APIs in eVault, file resolution utilities in the web3-adapter, and integrates file handling into the mapper's global/local conversion layer using a new __file directive.

Changes

File URI Scheme and Resolution

Layer / File(s) Summary
URI Scheme Foundation and Validation
infrastructure/web3-adapter/src/w3ds/uri.ts, infrastructure/web3-adapter/src/w3ds/uri.test.ts, infrastructure/evault-core/src/core/utils/w3ds-uri.ts
Defines the w3ds://file?id=@<ename>/<metaEnvelopeId> URI format with constants, buildFileUri and parseFileUri functions, validation logic, and comprehensive unit tests covering canonicalization, round-trip parsing, and error cases.
Storage Infrastructure and Configuration
.env.example, infrastructure/evault-core/package.json, infrastructure/evault-core/src/services/StorageService.ts
Configures DigitalOcean Spaces via new DO_SPACES_* environment variables, adds AWS SDK S3 client dependency, and implements StorageService with deterministic key building, configuration validation, and public URL generation for uploaded objects.
eVault File Upload GraphQL Mutation
infrastructure/evault-core/src/core/protocol/typedefs.ts, infrastructure/evault-core/src/core/protocol/graphql-server.ts
Extends GraphQL schema with UploadFileInput and UploadFilePayload types; implements uploadFile mutation resolver that validates X-ENAME, enforces 50MB size limit, uploads to storage, persists File meta-envelope with FILE_SCHEMA_ID ontology, and returns URI, meta-envelope ID, and public URL.
eVault File Dereference HTTP Endpoint
infrastructure/evault-core/src/core/http/server.ts
Adds GET /.files/:metaEnvelopeId route: validates X-ENAME header and parameter, looks up File meta-envelope, verifies ontology, extracts publicUrl, and issues 302 redirect or 404 error with descriptive messages.
File Dereferencing and Referencing Utilities
infrastructure/web3-adapter/src/w3ds/resolver.ts
Implements dereferenceFileUri to parse URIs, fetch meta-envelopes, validate public URLs, and return typed file metadata; referenceFile to upload files via EVaultClient and return URIs; and referenceFileValue to convert inline data: payloads into file URIs while preserving existing w3ds://file URIs.
EVaultClient GraphQL Upload Support
infrastructure/web3-adapter/src/evault/evault.ts
Extends EVaultClient with uploadFile method: executes eVault GraphQL mutation with retry/timeout wrappers, validates response structure, ensures required fields are present, and returns normalized UploadFileResult.
Web3Adapter Mapper Integration with File Directives
infrastructure/web3-adapter/src/mapper/mapper.types.ts, infrastructure/web3-adapter/src/mapper/mapper.ts, infrastructure/web3-adapter/src/index.ts
Augments IMappingConversionOptions with optional evaultClient; wires client into toGlobal and fromGlobal conversions in Web3Adapter; implements __file(<path>[,<alias>]) directive handling in mapper to upload/reference files on toGlobal and dereference file URIs on fromGlobal.
File URI Scheme and Mapper Documentation
infrastructure/web3-adapter/W3DS_URI.md, infrastructure/web3-adapter/MAPPING_RULES.md
Documents URI format, construction via buildFileUri, two dereferencing paths (HTTP endpoint with redirects and programmatic dereferenceFileUri), error handling, and mapper __file directive syntax and behavior.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant EVaultGraphQL
  participant StorageService
  participant DBService
  participant HTTPEndpoint
  
  Note over Client,DBService: File Upload Flow
  Client->>EVaultGraphQL: uploadFile(filename, content, contentType)
  EVaultGraphQL->>StorageService: uploadObject(buffer, contentType, key)
  StorageService-->>EVaultGraphQL: publicUrl
  EVaultGraphQL->>DBService: createMetaEnvelope(FILE_SCHEMA_ID, {size, blobKey, publicUrl})
  DBService-->>EVaultGraphQL: metaEnvelopeId
  EVaultGraphQL-->>Client: {uri: "w3ds://file?id=...", metaEnvelopeId, publicUrl}
  
  Note over Client,HTTPEndpoint: File Dereference Flow
  Client->>HTTPEndpoint: GET /.files/:metaEnvelopeId (X-ENAME)
  HTTPEndpoint->>DBService: getMetaEnvelope(ename, metaEnvelopeId)
  DBService-->>HTTPEndpoint: {ontology: "w3ds-file-v1", data: {publicUrl}}
  HTTPEndpoint-->>Client: 302 Redirect to publicUrl
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • MetaState-Prototype-Project/prototype#405: Both PRs tie into the same eVault request context via the X-ENAME header; this PR's file upload/dereference flows depend on X-ENAME validation, and the related PR updates how EVaultClient sends X-ENAME to the GraphQL endpoint.

Suggested labels

evault-refactor

Suggested reviewers

  • sosweetham
  • xPathin
  • JulienAuvo

Poem

🐰 Hops excitedly
Files now flutter on w3ds:// wings,
From upload to storage to redirect springs!
Meta-Envelopes hold the keys,
While mappers dance with __file at ease.
A chorus of URIs, perfectly formed,
The file-referencing dream is born! 🌟

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 70.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Feat/w3ds file uri' is vague and lacks clarity. It uses a generic feature prefix without conveying what file URI functionality was actually implemented. Improve the title to be more specific, such as 'Add w3ds://file URI scheme for file referencing and dereferencing' to clearly communicate the main change.
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The pull request description follows the template structure and includes required sections (issue number, type of change, checklist), but lacks substantial detail about the implementation and testing approach.
Linked Issues check ✅ Passed The PR comprehensively implements all acceptance criteria from issue #964: defines and documents the w3ds://file URI scheme with the specified pattern, implements resolver/dereferencer functionality, handles edge cases with proper validation, includes tests, and provides documentation updates.
Out of Scope Changes check ✅ Passed All changes directly support the w3ds://file URI scheme implementation from issue #964. File upload/storage infrastructure, GraphQL mutations, HTTP endpoints, mapper integration, and URI utilities are all necessary to meet the stated objectives.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/w3ds-file-uri

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.

@coodos coodos marked this pull request as ready for review May 18, 2026 18:09
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@infrastructure/evault-core/src/core/http/server.ts`:
- Around line 434-443: The handler currently reads publicUrl from
metaEnvelope.parsed and calls reply.redirect(publicUrl) without validating the
scheme; update the code around publicUrl (the variable extracted from
metaEnvelope.parsed) to parse and validate the URL’s protocol (e.g., using the
URL constructor) and only allow "http:" or "https:" before calling
reply.redirect(publicUrl); if the URL is invalid or uses a disallowed scheme,
return a safe error response (404/400) instead of redirecting to prevent unsafe
non-HTTP(S) redirects.

In `@infrastructure/evault-core/src/core/protocol/graphql-server.ts`:
- Around line 1229-1275: The upload flow currently uploads via new
StorageService().uploadObject then calls this.db.storeMetaEnvelope; if
storeMetaEnvelope fails the uploaded blob is orphaned—fix by attempting
compensating delete of the uploaded object inside the catch: after catching the
error (in the catch block that currently logs "uploadFile failed:"), if the
upload key (the `key` variable used for upload) and the StorageService instance
(`storage`) exist, await a cleanup call (e.g. storage.deleteObject or
equivalent) to remove the uploaded blob, log any cleanup error separately, and
then return the original UPLOAD_FAILED error response; update code references
around StorageService, uploadObject, `key`, and storeMetaEnvelope/buildFileUri
accordingly so the cleanup runs only for upload-success/database-failure cases.
- Around line 1189-1207: The current flow decodes input.content into base64 then
checks buffer.length, which misses malformed base64; instead validate
input.content (the derived base64 variable) before calling Buffer.from: ensure
it's non-empty, length % 4 === 0, and matches a strict pattern that allows only
A-Za-z0-9+/ and at most two '=' padding characters only at the end (e.g.
/^[A-Za-z0-9+/]+={0,2}$/ with additional logic to reject '=' in the middle), and
if validation fails return the existing INVALID_CONTENT error object; replace
the buffer.length === 0 check and only call Buffer.from(base64, "base64") after
the pre-validation succeeds (use the same field/message/code payload).

In `@infrastructure/evault-core/src/core/utils/w3ds-uri.ts`:
- Around line 13-16: The buildFileUri function accepts empty/raw inputs and
interpolates them directly into the id, producing invalid URIs; update
buildFileUri(eName, metaEnvelopeId) to validate that eName and metaEnvelopeId
are non-empty (throw or return an error), normalize eName to start with "@" (but
not include slashes), URL-encode both components with encodeURIComponent, and
then construct the final string as
`w3ds://file?id=${encodedEname}/${encodedMetaEnvelopeId}` so the produced URI is
safe to dereference.

In `@infrastructure/web3-adapter/MAPPING_RULES.md`:
- Around line 97-100: The example JSON in MAPPING_RULES.md repeats the same key
"avatar" twice in one object which is ambiguous; split them into two separate
JSON examples instead of duplicate keys. Update the snippet containing
`"avatar": "__file(avatar)"` and `"avatar": "__file(avatar),avatarUri"` so each
appears in its own fenced JSON block (separate examples) and ensure the fences
are labeled ```json and closed properly; keep the exact mapping strings
("__file(avatar)" and "__file(avatar),avatarUri") so readers can copy each
example unambiguously.

In `@infrastructure/web3-adapter/src/mapper/mapper.ts`:
- Around line 293-308: The code currently falls back to raw values when handling
a __file() match in the mapper (inside toGlobal), which can write non-w3ds://
payloads; change the else branch in the fileMatch handler so it fails fast
instead of passing rawVal through: when evaultClient or ownerEvault are missing,
throw a clear Error (or return a failure) that includes the localPath and alias
(use the existing variables fileTargetKey, localPath, alias) and a message that
__file() cannot be dereferenced due to missing evault client/owner; keep the
successful path using referenceFileValue(evaultClient, ownerEvault, rawVal)
unchanged so only fully-resolved w3ds:// file references are written to result.

In `@infrastructure/web3-adapter/src/w3ds/uri.ts`:
- Line 45: The return string builds the query id without encoding and can break
on reserved characters; change the id value to a properly encoded query
component by replacing ?id=${normalisedEname}/${metaEnvelopeId} with
?id=${encodeURIComponent(`${normalisedEname}/${metaEnvelopeId}`)} (or encode
each segment separately with encodeURIComponent(normalisedEname) + '/' +
encodeURIComponent(metaEnvelopeId) if you need to preserve the slash), updating
the return in the function that uses W3DS_SCHEME and W3DS_FILE_HOST so the id
query param is always URL-safe.

In `@infrastructure/web3-adapter/W3DS_URI.md`:
- Around line 8-10: The markdown fences are missing language identifiers causing
MD040; update the three fenced blocks that contain the strings
"w3ds://file?id=@<user-ename>/<meta-envelope-id>",
"w3ds://file?id=`@alice/envelope-abc123`", and "GET /.files/:metaEnvelopeId       
(header: X-ENAME: @<user-ename>)" to include appropriate languages (e.g.,
```text for the URI examples and ```http for the HTTP example) so the blocks
read like ```text ... ``` and ```http ... ``` to satisfy the lint rule.
- Around line 55-57: The documented dereference route in W3DS_URI.md currently
shows GET /files/:metaEnvelopeId (header: X-ENAME) but the implemented contract
in this PR uses GET /.files/:metaEnvelopeId; update the documentation to match
the implementation by replacing the path string `GET /files/:metaEnvelopeId`
with `GET /.files/:metaEnvelopeId` (and keep the header `X-ENAME:
@<user-ename>`), or alternatively if the intended canonical endpoint is
`/files/:metaEnvelopeId` adjust the implementation to expose that route; ensure
the document and the running contract both reference the exact same path (`GET
/.files/:metaEnvelopeId` vs `GET /files/:metaEnvelopeId`) to avoid client
mismatch.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3d979ba8-ae9d-4a5a-b5cc-90f8e13a9adf

📥 Commits

Reviewing files that changed from the base of the PR and between 7069493 and 1ac9ae8.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (16)
  • .env.example
  • infrastructure/evault-core/package.json
  • infrastructure/evault-core/src/core/http/server.ts
  • infrastructure/evault-core/src/core/protocol/graphql-server.ts
  • infrastructure/evault-core/src/core/protocol/typedefs.ts
  • infrastructure/evault-core/src/core/utils/w3ds-uri.ts
  • infrastructure/evault-core/src/services/StorageService.ts
  • infrastructure/web3-adapter/MAPPING_RULES.md
  • infrastructure/web3-adapter/W3DS_URI.md
  • infrastructure/web3-adapter/src/evault/evault.ts
  • infrastructure/web3-adapter/src/index.ts
  • infrastructure/web3-adapter/src/mapper/mapper.ts
  • infrastructure/web3-adapter/src/mapper/mapper.types.ts
  • infrastructure/web3-adapter/src/w3ds/resolver.ts
  • infrastructure/web3-adapter/src/w3ds/uri.test.ts
  • infrastructure/web3-adapter/src/w3ds/uri.ts

Comment thread infrastructure/evault-core/src/core/http/server.ts
Comment thread infrastructure/evault-core/src/core/protocol/graphql-server.ts
Comment thread infrastructure/evault-core/src/core/protocol/graphql-server.ts Outdated
Comment thread infrastructure/evault-core/src/core/utils/w3ds-uri.ts
Comment thread infrastructure/web3-adapter/MAPPING_RULES.md
Comment thread infrastructure/web3-adapter/src/mapper/mapper.ts
Comment thread infrastructure/web3-adapter/src/w3ds/resolver.ts
Comment thread infrastructure/web3-adapter/src/w3ds/uri.ts
Comment thread infrastructure/web3-adapter/W3DS_URI.md Outdated
Comment thread infrastructure/web3-adapter/W3DS_URI.md Outdated
@coodos coodos merged commit 0c93740 into main May 18, 2026
7 checks passed
@coodos coodos deleted the feat/w3ds-file-uri branch May 18, 2026 18:40
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.

Implement proper file URI referencing and dereferencing via w3ds:// URI scheme

1 participant