Skip to content

feat: add API conformance tooling and @relayfile/core package#11

Merged
khaliqgant merged 9 commits intomainfrom
feat/conformance-suite-and-skill
Mar 26, 2026
Merged

feat: add API conformance tooling and @relayfile/core package#11
khaliqgant merged 9 commits intomainfrom
feat/conformance-suite-and-skill

Conversation

@khaliqgant
Copy link
Member

@khaliqgant khaliqgant commented Mar 26, 2026

Summary

  • Conformance suite (scripts/conformance.ts): 23-test suite that verifies any relayfile-compatible server implements the API contract correctly. Runnable against any server via RELAYFILE_BASE_URL.
  • relayfile-workspace skill (.claude/skills/relayfile-workspace/SKILL.md): guidance for agents collaborating in a shared relayfile virtual filesystem.
  • @relayfile/core package (packages/core/): shared pure business logic extracted from relayfile-cloud's workspace.ts behind a StorageAdapter interface.

@relayfile/core contains

  • Semantics
  • Events
  • Tree
  • Query
  • Operations
  • Writeback
  • Webhooks
  • Export

Why this package exists

  • It extracts pure business logic from workspace.ts behind the StorageAdapter interface.
  • It keeps infrastructure-specific concerns in relayfile-cloud while centralizing the reusable domain logic.
  • A follow-up relayfile-cloud refactor will import this package from packages/core instead of keeping those implementations inline.

Test plan

  • npx tsx scripts/conformance.ts --ci passes 23/23 against Go server
  • npm run build passes in packages/core

khaliqgant and others added 2 commits March 26, 2026 12:25
Adds scripts/conformance.ts — a 23-test suite that verifies any
relayfile-compatible server correctly implements the API contract.
Both the Go server and the Cloudflare Workers server must pass this.

Runnable against any server URL via RELAYFILE_BASE_URL env var.

Covers: file CRUD, If-Match wildcard, conflict detection, cross-agent
metadata visibility, semantic queries (property/relation/comment),
ACL permission enforcement, WebSocket catch-up, writeback lifecycle,
bulk ops, export, concurrent multi-agent writes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds a skill that teaches agents how to work in a shared relayfile
virtual filesystem — covering metadata semantics, conflict handling,
discovery queries, ACL permissions, and collaboration patterns.

Designed for agents on platforms like Daytona where multiple agents
share the same workspace concurrently.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
devin-ai-integration[bot]

This comment was marked as resolved.

@khaliqgant khaliqgant changed the title feat: API conformance suite and relayfile-workspace skill feat: add API conformance tooling and @relayfile/core package Mar 26, 2026
devin-ai-integration[bot]

This comment was marked as resolved.

khaliqgant and others added 4 commits March 26, 2026 14:12
conformance.ts: correlation IDs now meet minLength:8 API spec requirement
writeback.ts: remove status reset to pending after successful send (infinite loop)
query.ts: fix spurious nextCursor when filters eliminate rows without hitting limit

Co-Authored-By: My Senior Dev <dev@myseniordev.com>
devin-ai-integration[bot]

This comment was marked as resolved.

Security fixes:
- webhooks.ts: ACL enforcement hook, signature verification callback,
  strip permissions from webhook-provided semantics, pagination guard
- files.ts: path traversal prevention via .. resolution in normalizePath
- files.ts: conflict response no longer leaks file content preview
- acl.ts: document default-open security model

Reliability fixes:
- semantics.ts: mergeSemantics now actually merges (was discarding existing)
- semantics.ts: size limits on arrays (MAX_ARRAY_ENTRIES=100)
- writeback.ts: correlationId parameter now used (was voided)
- writeback.ts: getPendingWritebacks filters by status=pending
- writeback.ts: dispatchWriteback sets status to dispatched after send
- export.ts: null guard on Response.body (was non-null assertion)
- storage.ts: document concurrency contract for StorageAdapter

Code quality:
- utils.ts: extract normalizePath with .. resolution (was duplicated 6x)
- files.ts: deduplicate normalizeSemantics (import from semantics.ts)

Testing:
- conformance.ts: health check captures and reports errors (was empty catch)
- conformance.ts: writeback test asserts items exist (was silently skipping)
- conformance.ts: typed interfaces replace pervasive any casts
- conformance.ts: ACL gap now tracked as test failure
- conformance.ts: JWT query string security concern documented

Co-Authored-By: My Senior Dev <dev@myseniordev.com>
Copy link
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 3 new potential issues.

View 15 additional findings in Devin Review.

Open in Devin Review

Comment on lines +170 to +177
function normalizePath(path: string): string {
const trimmed = path.trim();
if (!trimmed) {
return "/";
}
const prefixed = trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
return prefixed.length > 1 ? prefixed.replace(/\/+$/, "") : "/";
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🔴 ACL module uses local normalizePath without .. resolution while utils.ts has the secure version

The acl.ts module has a local normalizePath (line 170-177) that does NOT resolve . or .. segments, while utils.ts was specifically created to "resolve . and .. segments to prevent path traversal attacks" and is imported by files.ts for file writes. Since resolveFilePermissions is a public API exported from @relayfile/core (packages/core/src/index.ts:24), any external caller passing a path with .. segments (e.g., /finance/../secrets/data) would get incorrect ancestor directory resolution — the ACL walker would look for markers at /finance/.. instead of resolving to /. The same incomplete migration affects query.ts:123, tree.ts:135, operations.ts:116, and writeback.ts:158.

Prompt for agents
Replace the local normalizePath in packages/core/src/acl.ts (lines 170-177) with an import of the shared normalizePath from packages/core/src/utils.ts. The shared version resolves . and .. segments to prevent path traversal.

Specifically:
1. In packages/core/src/acl.ts, add: import { normalizePath } from "./utils.js";
2. Remove the local normalizePath function (lines 170-177)
3. Do the same for packages/core/src/query.ts (lines 123-130), packages/core/src/tree.ts (lines 135-142), packages/core/src/operations.ts (lines 116-123), and packages/core/src/writeback.ts (lines 158-165)

All five modules should import from ./utils.js instead of having their own copy that lacks .. resolution.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

contract.yml: <!-- devin-review-comment {"id": "BUG_pr-review-job-ca1d91a9d6c748
webhooks.ts: <!-- devin-review-comment {"id": "BUG_pr-review-job-ccdef9cc24a84af
webhooks.ts: <!-- devin-review-comment {"id": "BUG_pr-review-job-ccdef9cc24a84af
acl.ts: <!-- devin-review-comment {"id": "BUG_pr-review-job-ccdef9cc24a84af5abb6

Co-Authored-By: My Senior Dev <dev@myseniordev.com>
@khaliqgant khaliqgant force-pushed the feat/conformance-suite-and-skill branch from 5b2c1db to 35a042c Compare March 26, 2026 15:51
@khaliqgant khaliqgant merged commit 7210558 into main Mar 26, 2026
6 checks passed
@khaliqgant khaliqgant deleted the feat/conformance-suite-and-skill branch March 26, 2026 15:56
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