Skip to content

feat(notify): add dormant M5 upload attestation - #112

Merged
psimaker merged 3 commits into
mainfrom
agent/m5-upload-attestation
Jul 13, 2026
Merged

feat(notify): add dormant M5 upload attestation#112
psimaker merged 3 commits into
mainfrom
agent/m5-upload-attestation

Conversation

@psimaker

@psimaker psimaker commented Jul 13, 2026

Copy link
Copy Markdown
Owner

Summary

  • Implement Decision 024 message types 3–5 only: exact app-signed operation request, byte-identical attestation query, and helper-signed upload attestation.
  • Read and validate the complete request through the existing M4 confined namespace handle, then atomically persist one immutable attestation before returning the same bytes idempotently.
  • Enforce exact keys, epochs, bindings, operation, nonce, digest, TTL/skew, poll, start, request-rate, concurrency, restart, conflict, and tuple-isolation rules.
  • Add Go/Swift golden and negative coverage plus a build-tagged, network-isolated two-instance Syncthing E2E with fresh random request material.
  • Record the upload-only compatibility, privacy, retention, rollback, and NO-GO boundaries.

Explicit boundaries

Verification

  • cd notify && go test ./... -count=1 — pass on macOS (19.925s).
  • Digest-pinned Linux container go test ./... -count=1 with no network, read-only root, dropped capabilities, and no-new-privileges — pass (15.704s).
  • Targeted Linux race tests for concurrency, rate windows, and atomic publication — pass (2.358s).
  • cd notify && go vet ./... — pass.
  • cd notify && go test -run '^$' -fuzz '^FuzzDiagnosticsUploadDecoder$' -fuzztime=10s — pass (58,415 executions).
  • govulncheck ./... in notify — no vulnerabilities found.
  • Tagged Linux test compilation for amd64 and arm64 — pass.
  • Two ephemeral Syncthing instances with fresh random operation/request/query/helper material — pass (8.313s); a synchronized attestation copy is rejected as evidence.
  • go test -tags noassets ./bridge -count=1 — pass.
  • XCFramework build and XcodeGen generation — pass.
  • Targeted DiagnosticsUploadM5Tests with signing disabled — pass (32.269s).
  • Full iOS simulator build/test with signing disabled and temporary DerivedData — pass (46.990s).
  • M4 Docker host-bind confinement proof — all three tests pass.
  • Publish-safety policy — pass (8 negative cases, 1 exact positive model case).
  • actionlint v1.7.7 — pass, excluding only its known unsupported macos-26 runner-label diagnostic.
  • Design-token lint and four-locale string parity (759 keys) — pass.
  • Diff formatting, attribution, private-key/high-entropy secret, and release-metadata scans — clean.

Compatibility, privacy, and rollback

  • Current app × current helper and current app × source-with-M5 behave exactly as before because no entry point references M5.
  • An M5 test client against the current product helper is unsupported/capability unavailable and gains no fallback evidence.
  • Operation values exist only in test memory and authenticated temporary namespace artifacts; no logger, telemetry, crash annotation, support export, operation database, Relay, APNs, StoreKit, UserDefaults, or Keychain carrier is added.
  • Cleanup remains evidence-orthogonal. Backups, versions, conflicts, and tombstones may retain opaque copies, but TTL and the exact active signed chain prevent later acceptance.
  • Rollback is a source revert with no product migration, wire rollback, credential deletion, namespace deletion, or user-data change.

Release truth

VaultSync 2.0 remains NO-GO.

  • Upload: implemented only as an exact local test/mock proof through the confined namespace and pinned mock channel.
  • Download: unset and not implemented.
  • Roundtrip: unset and not implemented.
  • Authenticated correlation: test/mock only for the exact active app/homeserver/folder/helper/operation/key-epoch chain.
  • Helper-first publication, rollout, upgrade, downgrade, and both rollback directions: not performed or verified.
  • App runtime and all post-M5 runtime work remain blocked pending separate owner scope and milestone gates.

psimaker added 3 commits July 13, 2026 20:11
Implement the Decision 024 upload-only protocol and helper attestor behind the existing dormant diagnostics boundary.

Validate exact signed request/query chains through M4 confinement, atomically persist immutable attestations, enforce tuple/rate/restart limits, and add Go/Swift golden, model, privacy, crash, race, and restart coverage.

Keep helper and app product entry points unchanged; no capability, listener, response, download, roundtrip, or Relay integration is enabled.
Add a build-tagged two-instance local Syncthing test with fresh random request material for request propagation, confined helper observation, durable attestation, pinned mock acceptance, and rejection of synchronized copies as evidence.

Run it in CI with immutable action refs, read-only mounts, no network, dropped capabilities, no persisted checkout credentials, and a digest-pinned Go image. No test artifact is uploaded or published.
Document the upload-only test claim, compatibility matrix, privacy and retention behavior, rollback, unsupported runtime surfaces, and the remaining helper-first gates.

VaultSync 2.0 remains NO-GO; download, roundtrip, runtime, packaging, publication, rollout, and release work remain unapproved.
@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a dormant Decision 024 upload-attestation foundation with strict CBOR and cryptographic validation, atomic helper persistence, Swift and Go tests, isolated Syncthing E2E coverage, documentation, privacy-boundary checks, and CI integration.

Changes

M5 upload-attestation foundation

Layer / File(s) Summary
Upload protocol and cross-language contracts
notify/diagnostics_upload_protocol.go, notify/diagnostics_upload_protocol_test.go, ios/VaultSyncTests/Fixtures/*
Defines signed CBOR request, query, and attestation messages with chain validation, golden fixtures, fail-closed parsing, and fuzz coverage.
Swift acceptance model and golden verification
ios/VaultSyncTests/DiagnosticsUploadM5TestSupport.swift, ios/VaultSyncTests/DiagnosticsUploadM5Tests.swift
Adds deterministic Swift message verification, pinned-response acceptance modeling, evidence isolation, limits, and property tests.
Atomic persistence and helper attestor
notify/diagnostics_namespace_filesystem_*, notify/diagnostics_upload_attestor.go, notify/diagnostics_upload_attestor_linux_test.go
Implements atomic immutable publication, attestation signing and persistence, authorization checks, replay handling, rate limits, and concurrency controls.
Two-instance Syncthing validation
notify/diagnostics_upload_syncthing_e2e_test.go, .github/workflows/ci.yml
Runs a hardened isolated E2E test covering request synchronization, pinned attestation validation, copied-artifact handling, and namespace consistency.
Dormant boundaries and documentation
docs/*, PRIVACY.md, CHANGELOG.md, notify/README.md, notify/diagnostics_contract_model_test.go
Documents test-only scope and extends checks preventing runtime, privacy, capability, and later-phase carriers.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

  • psimaker/vaultsync#107: Extends the diagnostics contract foundation that this PR augments with upload-carrier checks.
  • psimaker/vaultsync#109: Adds related dormant diagnostics contract exceptions for another Decision 024-adjacent foundation.

Suggested reviewers: dependabot[bot]

Poem

Three signed messages cross the night,
Atomic bytes arrive just right.
Two quiet nodes exchange their tune,
Tests guard the path beneath the moon—
Dormant foundations, sealed and bright.

🚥 Pre-merge checks | ✅ 7
✅ Passed checks (7 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
No Private Note Leakage ✅ Passed No logging/telemetry sinks or sensitive-value interpolation found; the only API-key use is a loopback Syncthing test header, with crash reporting and external networking disabled.
Bounded Ios Background Work ✅ Passed PASS: PR only adds synchronous M5 Swift test models/tests; no Swift BGTask/expiration code changed, and the real background-service code is untouched.
Bridge Contract Compatibility ✅ Passed No Go bridge or Swift bridge-service files changed, and the existing bridge contract tests for pong/version/arch remain intact.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise, conventional-commit style, and accurately summarizes the main dormant M5 upload attestation change.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch agent/m5-upload-attestation

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.

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
notify/diagnostics_upload_syncthing_e2e_test.go (1)

216-218: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider t.Context() over context.Background() in test helpers.

Since Go 1.24, testing.TB.Context() returns a context auto-canceled right before t.Cleanup runs, which is a slightly more idiomatic fit than context.Background() for the various short-lived exec/HTTP calls throughout this file (e.g. Lines 216, 248, 491). Purely stylistic here since each call already has its own timeout — not blocking.

🤖 Prompt for 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.

In `@notify/diagnostics_upload_syncthing_e2e_test.go` around lines 216 - 218,
Update the test helper call sites that create short-lived operation contexts,
including the flow around exec.CommandContext, to derive them from t.Context()
instead of context.Background(). Preserve each existing timeout and cleanup
behavior, and apply the same change to the analogous call sites throughout the
file.
.github/workflows/ci.yml (1)

106-109: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Gate the Ubuntu test jobs on docs-only changes The docs-only skip currently applies only to build; m5-syncthing-upload-e2e and the other non-macOS test jobs still run on documentation-only PRs. Add the same needs.changes / if: needs.changes.outputs.code == 'true' guard here if the goal is to save CI minutes.

🤖 Prompt for 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.

In @.github/workflows/ci.yml around lines 106 - 109, Gate
m5-syncthing-upload-e2e and the other non-macOS test jobs using the same
needs.changes dependency and needs.changes.outputs.code == 'true' condition as
build, so documentation-only changes skip these jobs while code changes continue
to run them.
🤖 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.

Nitpick comments:
In @.github/workflows/ci.yml:
- Around line 106-109: Gate m5-syncthing-upload-e2e and the other non-macOS test
jobs using the same needs.changes dependency and needs.changes.outputs.code ==
'true' condition as build, so documentation-only changes skip these jobs while
code changes continue to run them.

In `@notify/diagnostics_upload_syncthing_e2e_test.go`:
- Around line 216-218: Update the test helper call sites that create short-lived
operation contexts, including the flow around exec.CommandContext, to derive
them from t.Context() instead of context.Background(). Preserve each existing
timeout and cleanup behavior, and apply the same change to the analogous call
sites throughout the file.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 5aaa2867-2f9e-4f98-b170-e941df4bf1a0

📥 Commits

Reviewing files that changed from the base of the PR and between c2711c0 and edc9c81.

📒 Files selected for processing (17)
  • .github/workflows/ci.yml
  • CHANGELOG.md
  • PRIVACY.md
  • docs/architecture.md
  • docs/m5-upload-attestation-readiness.md
  • ios/VaultSyncTests/DiagnosticsUploadM5TestSupport.swift
  • ios/VaultSyncTests/DiagnosticsUploadM5Tests.swift
  • ios/VaultSyncTests/Fixtures/diagnostics-upload-m5.json
  • notify/README.md
  • notify/diagnostics_contract_model_test.go
  • notify/diagnostics_namespace_filesystem_linux.go
  • notify/diagnostics_namespace_filesystem_unsupported.go
  • notify/diagnostics_upload_attestor.go
  • notify/diagnostics_upload_attestor_linux_test.go
  • notify/diagnostics_upload_protocol.go
  • notify/diagnostics_upload_protocol_test.go
  • notify/diagnostics_upload_syncthing_e2e_test.go
📜 Review details
🧰 Additional context used
📓 Path-based instructions (12)
**

⚙️ CodeRabbit configuration file

**:

VaultSync

VaultSync

Self-hosted Obsidian vault sync for iPhone and iPad.

Your notes sync peer-to-peer over Syncthing, straight into Obsidian's iOS sandbox — no note cloud, no account, no tracking.

Download on the App Store



Stars
License: MPL-2.0
iOS 18+
CI

VaultSync welcome screen VaultSync home screen

🔭 Why VaultSync

  • Peer-to-peer & private — syncs directly between your own devices over Syncthing. No note cloud, no account, no tracking.
  • Lands in Obsidian — files sync into Obsidian's iOS sandbox, where the app already looks for them.
  • Pair by QR, resolve conflicts — connect your server in seconds; settle Markdown conflicts with side-by-side diffs.
  • Server changes can wake your iPhone — optional Cloud Relay asks iOS to wake the app after the helper observes a server change. T...

Files:

  • ios/VaultSyncTests/Fixtures/diagnostics-upload-m5.json
  • notify/diagnostics_namespace_filesystem_unsupported.go
  • PRIVACY.md
  • CHANGELOG.md
  • docs/m5-upload-attestation-readiness.md
  • notify/README.md
  • ios/VaultSyncTests/DiagnosticsUploadM5TestSupport.swift
  • docs/architecture.md
  • notify/diagnostics_upload_protocol.go
  • notify/diagnostics_contract_model_test.go
  • notify/diagnostics_upload_syncthing_e2e_test.go
  • notify/diagnostics_namespace_filesystem_linux.go
  • notify/diagnostics_upload_attestor_linux_test.go
  • notify/diagnostics_upload_attestor.go
  • notify/diagnostics_upload_protocol_test.go
  • ios/VaultSyncTests/DiagnosticsUploadM5Tests.swift
**/*

⚙️ CodeRabbit configuration file

**/*: VaultSync syncs private Obsidian notes through Syncthing. Treat data loss,
privacy leaks, security regressions, and broken sync behavior as high priority.
Do not nitpick formatting unless it affects maintainability, correctness, or public API clarity.
Flag any accidental logging, telemetry, crash reporting, or network transfer of note contents,
vault paths, filenames with private context, API keys, APNs tokens, relay keys, or security-scoped bookmark data.

Files:

  • ios/VaultSyncTests/Fixtures/diagnostics-upload-m5.json
  • notify/diagnostics_namespace_filesystem_unsupported.go
  • PRIVACY.md
  • CHANGELOG.md
  • docs/m5-upload-attestation-readiness.md
  • notify/README.md
  • ios/VaultSyncTests/DiagnosticsUploadM5TestSupport.swift
  • docs/architecture.md
  • notify/diagnostics_upload_protocol.go
  • notify/diagnostics_contract_model_test.go
  • notify/diagnostics_upload_syncthing_e2e_test.go
  • notify/diagnostics_namespace_filesystem_linux.go
  • notify/diagnostics_upload_attestor_linux_test.go
  • notify/diagnostics_upload_attestor.go
  • notify/diagnostics_upload_protocol_test.go
  • ios/VaultSyncTests/DiagnosticsUploadM5Tests.swift
notify/**/*.{sh,go}

📄 CodeRabbit inference engine (README.md)

The optional notify sidecar must support server-side wake-up requests and must not receive notes, file or folder names, or vault structure.

Files:

  • notify/diagnostics_namespace_filesystem_unsupported.go
  • notify/diagnostics_upload_protocol.go
  • notify/diagnostics_contract_model_test.go
  • notify/diagnostics_upload_syncthing_e2e_test.go
  • notify/diagnostics_namespace_filesystem_linux.go
  • notify/diagnostics_upload_attestor_linux_test.go
  • notify/diagnostics_upload_attestor.go
  • notify/diagnostics_upload_protocol_test.go
**/*.{md,sh,go,swift}

📄 CodeRabbit inference engine (README.md)

Keep Relay-side request observation and wake-ups received on the iPhone as separate diagnostics evidence; one must not be treated as proof of the other.

Files:

  • notify/diagnostics_namespace_filesystem_unsupported.go
  • PRIVACY.md
  • CHANGELOG.md
  • docs/m5-upload-attestation-readiness.md
  • notify/README.md
  • ios/VaultSyncTests/DiagnosticsUploadM5TestSupport.swift
  • docs/architecture.md
  • notify/diagnostics_upload_protocol.go
  • notify/diagnostics_contract_model_test.go
  • notify/diagnostics_upload_syncthing_e2e_test.go
  • notify/diagnostics_namespace_filesystem_linux.go
  • notify/diagnostics_upload_attestor_linux_test.go
  • notify/diagnostics_upload_attestor.go
  • notify/diagnostics_upload_protocol_test.go
  • ios/VaultSyncTests/DiagnosticsUploadM5Tests.swift
notify/**/*.go

⚙️ CodeRabbit configuration file

notify/**/*.go: Review goroutine lifecycle, context cancellation, HTTP timeouts, signal handling, debounce behavior,
Syncthing REST API polling, relay API calls, error classification, and API-key handling.
Flag leaked request bodies, note metadata, Syncthing API keys, relay keys, or APNs-related secrets.

Files:

  • notify/diagnostics_namespace_filesystem_unsupported.go
  • notify/diagnostics_upload_protocol.go
  • notify/diagnostics_contract_model_test.go
  • notify/diagnostics_upload_syncthing_e2e_test.go
  • notify/diagnostics_namespace_filesystem_linux.go
  • notify/diagnostics_upload_attestor_linux_test.go
  • notify/diagnostics_upload_attestor.go
  • notify/diagnostics_upload_protocol_test.go
**/*.md

⚙️ CodeRabbit configuration file

**/*.md: Review public documentation for technical accuracy, privacy/security claims, App Store-facing wording,
setup correctness, and consistency with the free app plus optional Cloud Relay subscription model.

Files:

  • PRIVACY.md
  • CHANGELOG.md
  • docs/m5-upload-attestation-readiness.md
  • notify/README.md
  • docs/architecture.md
docs/**/*.md

📄 CodeRabbit inference engine (docs/troubleshooting.md)

docs/**/*.md: After applying each troubleshooting fix, retry from the app to confirm whether the issue is resolved.
For a missing Device ID or “Sync Engine Not Running,” force-close and reopen VaultSync, keep it foregrounded for 20–30 seconds, confirm the Device ID, rescan the vault, and reboot if necessary.
vaultsync-notify must read the Syncthing API key from config.xml; permission or authentication failures should be diagnosed as wrong-file or read-permission problems before changing credentials.
Run vaultsync-notify as the user owning Syncthing’s mode-0600 config.xml, or configure the appropriate container PUID/PGID.
Set SYNCTHING_CONFIG when the Syncthing configuration is not auto-detected, and remove or correct SYNCTHING_API_KEY overrides that replace automatic detection.
For relay failures, verify internet access, RELAY_URL, server egress rules, relay health with curl, and the app’s relay diagnostics; confirm delivery through an updated “Last Trigger Received” timestamp.
A relay HTTP 429 from --doctor counts as success because it proves the trigger endpoint is reachable; an inactive subscription is a warning fixed through app subscription or provisioning.
Peer-state warnings from --doctor must not fail the command: offline peers are normal, and --healthcheck must skip peer-state diagnostics.
For missing pending shares, verify the desktop folder shares the exact iOS Device ID, ensure Syncthing is online and unpaused, refresh pending shares, and re-share if needed.
For APNs issues, retry APNs registration, verify a token appears, retry provisioning, and confirm delivery with “Last Trigger Received”; notification permission is not required for silent wake-ups.
When connecting Obsidian storage, choose On My iPhone → Obsidian or the vault root containing .obsidian, then confirm detected vaults or pending shares.
VaultSync must not move, recreate, or delete vault folders automatically; recovery from moved or deleted folders requires ma...

Files:

  • docs/m5-upload-attestation-readiness.md
  • docs/architecture.md
docs/**

⚙️ CodeRabbit configuration file

docs/**: # Architecture

VaultSync embeds Syncthing's Go reference implementation as an iOS library via gomobile — no reimplementation of the protocol in Swift, and guaranteed wire compatibility.

┌─────────────────────────────────┐
│         SwiftUI Frontend        │   iOS-native UI, Swift 6
├─────────────────────────────────┤
│       Swift ↔ Go Bridge         │   thin API via gomobile
│                                 │   → exported as .xcframework
├─────────────────────────────────┤
│        syncthing/lib (Go)       │   protocol, discovery, sync
└─────────────────────────────────┘
              ↕ filesystem
┌─────────────────────────────────┐
│    Obsidian Vault (direct)      │   Obsidian's iOS sandbox
└─────────────────────────────────┘

🔄 Sync strategy

  • Foreground — Syncthing runs unrestricted: immediate, continuous sync.
  • BackgroundBGAppRefreshTask (requested ~15 min out; iOS decides the actual timing) + BGProcessingTask (overnight catch-up: multi-minute budget while charging with network) + BGContinuedProcessingTask (iOS 26+, longer runtime for user-initiated tasks). A ~30s grace window after backgrounding lets in-flight work finish.
  • Push (Cloud Relay) — optional. Near-realtime server → iPhone wake-ups via APNs silent push. See relay-spec.md.

VaultSync is intentionally asymmetric:

Direction Path
Server → iPhone vaultsync-notify spots outgoing changes → Cloud Relay silent push → VaultSync wakes and pulls.
iPhone → Server iOS doesn't guarantee timely background execution for local edits. The reliable path is to open VaultSync and let embedded Syncthing run in the foreground — a Shortcuts automation can do that automatically whenever you leave Obsidian.

Cloud Relay is a server → iPhone acceleration path, not a guarantee of symmetric real-time background sync.

Relay and sync proof hierarchy

VaultSync models proof as independent fi...

Files:

  • docs/m5-upload-attestation-readiness.md
  • docs/architecture.md
**/*.swift

📄 CodeRabbit inference engine (Custom checks)

For Swift background execution changes, pass if work is bounded, cancellation-aware, handles expiration callbacks, and records errors without leaking private vault data. Fail only when background work can continue unbounded, miss cleanup, or violate iOS background execution constraints.

Files:

  • ios/VaultSyncTests/DiagnosticsUploadM5TestSupport.swift
  • ios/VaultSyncTests/DiagnosticsUploadM5Tests.swift
ios/**/*.swift

📄 CodeRabbit inference engine (README.md)

ios/**/*.swift: Develop the iOS/iPadOS app using Swift 6 and SwiftUI, targeting iOS/iPadOS 18 or later.
Use VoiceOver and Dynamic Type throughout the iOS/iPadOS app.
Support localization in English, German, Spanish, and Simplified Chinese.

Files:

  • ios/VaultSyncTests/DiagnosticsUploadM5TestSupport.swift
  • ios/VaultSyncTests/DiagnosticsUploadM5Tests.swift

⚙️ CodeRabbit configuration file

ios/**/*.swift: Focus on Swift 6 strict concurrency, Sendable/MainActor correctness, Task cancellation,
retain cycles, memory pressure, SwiftUI observation state, StoreKit/APNs flows, and iOS background execution limits.
Pay special attention to BGAppRefreshTask and BGContinuedProcessingTask behavior, expiration handling,
bounded work, and cleanup when the app is suspended or terminated.

Files:

  • ios/VaultSyncTests/DiagnosticsUploadM5TestSupport.swift
  • ios/VaultSyncTests/DiagnosticsUploadM5Tests.swift
ios/**/*.{swift,plist}

📄 CodeRabbit inference engine (README.md)

ios/**/*.{swift,plist}: Use BGAppRefreshTask and BGContinuedProcessingTask when available for background processing, while allowing iOS to decide whether and when the app runs.
Implement APNs silent push handling for optional Cloud Relay wake-ups.

Files:

  • ios/VaultSyncTests/DiagnosticsUploadM5TestSupport.swift
  • ios/VaultSyncTests/DiagnosticsUploadM5Tests.swift
.github/workflows/**/*.yml

⚙️ CodeRabbit configuration file

.github/workflows/**/*.yml: Review CI for correct Go test tags, Xcode/iOS simulator assumptions, secret scoping,
dependency integrity, permissions, Docker publishing safety, and unnecessary privilege escalation.

Files:

  • .github/workflows/ci.yml
🧠 Learnings (2)
📓 Common learnings
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-13T18:23:34.669Z
Learning: Run Syncthing unrestricted in the foreground for immediate continuous synchronization.
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-13T18:23:34.669Z
Learning: Treat Cloud Relay as an optional server-to-iPhone acceleration path, not as a guarantee of symmetric real-time background synchronization.
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-13T18:23:34.669Z
Learning: Model synchronization proof as independent evidence fields; never derive stronger proof from weaker evidence or use one generic “sync succeeded” flag.
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-13T18:23:34.669Z
Learning: Do not treat relay reachability, trigger observation, push receipt, background start, engine reachability, scans, index updates, idle state, or 100% completion as local data progress; only a fresh successful incoming `ItemFinished` application qualifies.
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-13T18:23:34.669Z
Learning: Keep push receipt, background start, and organic background progress iPhone-wide and unattributed; only a manual check may scope fresh local evidence to one folder and its sole configured peer.
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-13T18:23:34.669Z
Learning: Manual synchronization checks must be passive: they may not create probe artifacts, rescan, write files, modify mappings or ignores, persist check identifiers/results, or run during onboarding, launch, silent push, or ordinary background sync.
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-13T18:23:34.669Z
Learning: Manual checks must enforce eligibility, freshness, generation, polling, staleness, cancellation, and conservative failure rules: only eligible single-peer folders qualify; evidence must be newer than the check start and baseline cursor; generation changes interrupt; results stale after 15 minutes; failures never produce false success.
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-13T18:23:34.669Z
Learning: Keep dormant pairing, namespace, and correlated-roundtrip foundations unreachable from production runtime; do not add installer, endpoint, listener, capability, folder-creation, or app-enablement paths without an authorized rollout decision.
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-13T18:23:34.669Z
Learning: Do not implement upload, controlled-download, or full-roundtrip proof until the separately designed, capability-negotiated helper contract and safe app-owned diagnostics namespace are available.
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-13T18:23:41.835Z
Learning: Keep M5 upload-only and dormant: it must not authorize or provide helper runtime, App runtime, capability negotiation, packaging, publication, rollout, controlled download, or causal roundtrip; VaultSync 2.0 remains NO-GO.
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-13T18:23:41.835Z
Learning: Implement only Decision 024 deterministic CBOR messages 3–5: `operation_request`, `attestation_query`, and `upload_attestation`.
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-13T18:23:41.835Z
Learning: Require exact payload and authentication constraints, including 256-byte request payloads, SHA-256 domain/payload digests, Ed25519 signatures and key IDs, nonzero operation/nonces, exact bindings/epochs, and a 600-second TTL with 120-second clock skew.
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-13T18:23:41.835Z
Learning: Ensure helper reads requests only through the M4 confined root handle after validating authenticated namespace authorization.
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-13T18:23:41.835Z
Learning: Persist attestations atomically by writing and fsyncing an anonymous inode, linking it once to the final filename, fsyncing the directory, and returning the persisted bytes; partial final names and overwrites must be impossible.
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-13T18:23:41.835Z
Learning: Repeated exact queries and helper restarts may return only the exact authenticated persisted attestation; conflicting queries or artifacts must never upgrade evidence.
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-13T18:23:41.835Z
Learning: Enforce all stated operation, poll, start, and request rate limits, and count invalid requests against the applicable limits.
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-13T18:23:41.835Z
Learning: Swift parsing and upload acceptance must remain test-target-only and require the exact pinned mock channel and active query; pending state, HTTP acceptance, reachability, timestamps, and synchronized copies must not set upload.
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-13T18:23:41.835Z
Learning: Do not implement capability query/response, runtime flags, local endpoints, TLS, listeners, response authorization or artifacts, authenticated cleanup messages, download evidence, roundtrip, product UI, automatic discovery, namespace creation, pairing/trust adoption, or durable operation history in M5.
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-13T18:23:41.835Z
Learning: Preserve existing product behavior: current product app/helper combinations and existing setup and wire behavior must remain unchanged, and product state must require no migration.
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-13T18:23:41.835Z
Learning: Fail closed for rotated, revoked, lost, or mismatched keys, epochs, or bindings; require explicit re-pairing or re-authorization and never transfer trust automatically.
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-13T18:23:41.835Z
Learning: Cleanup may delete only a previously owned file whose descriptor-relative identity and digest still match; it must never target protected roots, metadata, credentials, user files, backups, history, or tombstones.
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-13T18:23:41.835Z
Learning: Do not add logging, telemetry, crash annotations, support exports, persistent credentials, production service clients, or production Syncthing configuration changes; E2E tests must use temporary isolated homes and folders.
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-13T18:23:41.835Z
Learning: Rollback M5 by source revert only; remove test artifacts from temporary directories, and do not require product migration or wire rollback.
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-13T18:23:41.835Z
Learning: After merge, compare Decisions 021–025 with the actual code, require separate owner scope approval for response/cleanup foundations, and retain independent PR and owner merge gates for later milestones.
📚 Learning: 2026-07-12T23:03:04.680Z
Learnt from: psimaker
Repo: psimaker/vaultsync PR: 107
File: ios/VaultSyncTests/DiagnosticsContractTests.swift:39-46
Timestamp: 2026-07-12T23:03:04.680Z
Learning: In iOS Swift tests that use CryptoKit’s `Curve25519.Signing.PrivateKey.signature(for:)` (Ed25519), don’t assert that a generated signature’s bytes exactly match deterministic “golden”/fixture signatures. CryptoKit signatures may be randomized (different but valid for the same key+message). Instead, verify correctness by calling `isValidSignature` (or equivalent) against (1) the golden bytes and (2) the freshly generated signature, and avoid byte-for-byte equality assertions between CryptoKit output and reference vectors.

Applied to files:

  • ios/VaultSyncTests/DiagnosticsUploadM5TestSupport.swift
  • ios/VaultSyncTests/DiagnosticsUploadM5Tests.swift
🪛 ast-grep (0.44.1)
notify/diagnostics_upload_syncthing_e2e_test.go

[error] 227-230: An argument passed to exec.Command/exec.CommandContext is built by concatenating a string literal with dynamic input. If that input is attacker-controlled (and especially when the command is a shell such as sh -c/bash -c), this enables OS command injection. Pass untrusted data as separate, fixed arguments instead of interpolating it into a command string, avoid invoking a shell, and validate/escape the input where a shell is unavoidable.
Context: exec.Command(
binary, "serve", "--home", home, "--gui-address=http://"+guiAddress, "--gui-apikey="+instance.apiKey,
"--no-browser", "--no-restart", "--no-upgrade", "--no-port-probing", "--log-level=WARN", "--log-file=-",
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(command-injection-exec-concat-arg-go)

notify/diagnostics_namespace_filesystem_linux.go

[warning] 272-272: Narrowing a non-constant integer to a smaller fixed-width type (int8/int16/int32, uint8/uint16/uint32) can silently overflow or wrap, yielding negative or truncated values that are dangerous in size, length, or index logic. Validate the source value is within the target type's range before converting (e.g. bounds-check, or use a checked helper), and avoid narrowing untrusted or len()/parsed values.
Context: uint32(os.Geteuid())
Note: [CWE-190] Integer Overflow or Wraparound.

(integer-overflow-narrowing-conversion-go)

🔇 Additional comments (26)
notify/diagnostics_upload_syncthing_e2e_test.go (1)

1-119: LGTM!

Also applies to: 121-177, 205-320, 341-507

notify/diagnostics_upload_protocol.go (3)

42-98: LGTM!


237-299: LGTM!


118-128: 🎯 Functional Correctness

No CBOR ordering gap here The Go decoder rejects non-canonical map encodings before validateDiagnosticsUploadValue runs, so this sort does not introduce a Go/Swift parity gap.

			> Likely an incorrect or invalid review comment.
docs/m5-upload-attestation-readiness.md (1)

1-95: LGTM!

notify/diagnostics_upload_protocol_test.go (1)

63-345: LGTM!

ios/VaultSyncTests/DiagnosticsUploadM5TestSupport.swift (3)

74-216: LGTM!


330-355: LGTM!


409-500: LGTM!

ios/VaultSyncTests/DiagnosticsUploadM5Tests.swift (1)

7-304: LGTM!

ios/VaultSyncTests/Fixtures/diagnostics-upload-m5.json (1)

1-33: LGTM!

CHANGELOG.md (1)

11-11: LGTM!

PRIVACY.md (1)

84-96: LGTM!

docs/architecture.md (2)

94-94: LGTM!

Also applies to: 146-171


134-145: 🎯 Functional Correctness

No change needed — these limits match notify/diagnostics_upload_attestor.go and notify/diagnostics_upload_protocol.go.

			> Likely an incorrect or invalid review comment.
notify/README.md (1)

155-173: LGTM!

notify/diagnostics_contract_model_test.go (2)

290-290: LGTM!

Also applies to: 321-322, 365-366


406-458: LGTM!

.github/workflows/ci.yml (2)

228-228: LGTM!


106-146: 🩺 Stability & Availability

No issue: the containerized Go test stays self-contained. The pinned golang image matches notify/go.mod’s go 1.26.5, and notify only imports stdlib packages, so the --network none / read-only setup does not block module or toolchain resolution here.

			> Likely an incorrect or invalid review comment.
notify/diagnostics_namespace_filesystem_linux.go (3)

182-254: LGTM!


256-282: LGTM!


284-302: 🩺 Stability & Availability

This path is part of the dormant diagnostics foundation, so the linkat(AT_EMPTY_PATH) kernel caveat doesn’t apply to current product behavior.

			> Likely an incorrect or invalid review comment.
notify/diagnostics_namespace_filesystem_unsupported.go (1)

21-23: LGTM!

notify/diagnostics_upload_attestor.go (1)

168-461: LGTM!

notify/diagnostics_upload_attestor_linux_test.go (1)

17-462: LGTM!

@psimaker
psimaker marked this pull request as ready for review July 13, 2026 18:51
@psimaker
psimaker merged commit 93e6c22 into main Jul 13, 2026
25 checks passed
@psimaker
psimaker deleted the agent/m5-upload-attestation branch July 13, 2026 18:52
@psimaker
psimaker restored the agent/m5-upload-attestation branch July 13, 2026 19:52
@psimaker
psimaker deleted the agent/m5-upload-attestation branch July 22, 2026 12:49
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