Skip to content

fix: Foundry hardening — sealed RLS, VecDeque audit, URL decode, Plugin handshake#280

Merged
AdaWorldAPI merged 5 commits into
mainfrom
claude/foundry-fixes-r2-2026-04-29
Apr 29, 2026
Merged

fix: Foundry hardening — sealed RLS, VecDeque audit, URL decode, Plugin handshake#280
AdaWorldAPI merged 5 commits into
mainfrom
claude/foundry-fixes-r2-2026-04-29

Conversation

@AdaWorldAPI
Copy link
Copy Markdown
Owner

Summary

Addresses all CRITICAL + HIGH + MEDIUM findings from PR #278 review:

  • CRITICAL — Sealed RLS registry default. RegistryMode::Sealed is now the default; unregistered TableScans return DataFusionError::Plan. Fail-open requires explicit RlsPolicyRegistry::fail_open("reason"). Matches foundry-roadmap.md deny-by-default contract.
  • HIGH — RlsContext::new validates inputs. Empty tenant_id / actor_idErr(RlsError). Legacy new_unchecked preserved for system contexts.
  • HIGH — Audit ring O(1). Vec::remove(0)VecDeque::pop_front().
  • HIGH — Stable FNV-64a hash. DefaultHasher replaced with hand-rolled FNV-1a (cross-build deterministic).
  • HIGH — PostgREST URL decoding. %XX and + decoded in filter values, select=, order=.
  • HIGH — gate_f resolved. GATE_DAMPING_FACTOR = 0.5 separates it from free_e (Option B; field kept for SQL filter schema compat).
  • MEDIUM — Acquire/Release atomics on current_scent and current_rationale_phase.
  • MEDIUM — Plugin handshake. Plugin trait with name(), depends_on(), seal() for boot-time prerequisite verification (E2).
  • MEDIUM — AuditSink: Debug bound added so MembraneRegistry derives Debug under --all-features.
  • MEDIUM — Table name validation rejects ../../../etc/passwd and non-alnum characters.
  • E3 — LogicalPlan retention. AuditEntry.rewritten_plan: Option<String> for retroactive policy enforcement.

Stats

  • 5 files changed, +939 / -63 lines
  • 5 commits (4 workers + 1 meta integration)
  • 58 tests pass (auth-rls-lite)
  • All feature combos green (default, query-lite, auth-rls-lite, audit-log, postgrest, all-features)

Test plan

  • cargo check -p lance-graph-callcenter --all-features — green
  • cargo test -p lance-graph-callcenter --features auth-rls-lite --lib — 58 passed
  • Sealed registry errors on unregistered table
  • Fail-open registry passes through (explicit opt-in)
  • Empty tenant_id / actor_id rejected
  • VecDeque ring overflow drops oldest (O(1))
  • FNV hash pinned against canonical vectors
  • URL decode %20 → space, %40@, + → space
  • Table name ../../../etc/passwd rejected
  • Concurrent 8-thread append no-loss
  • Integration test: sealed RLS + audit log captures rewritten plan

https://claude.ai/code/session_01SbYsmmbPf9YQuYbHZN52Zh

claude added 5 commits April 29, 2026 05:43
- Added Send + Sync + Debug bound on AuditSink trait so MembraneRegistry
  can derive Debug under --all-features
- Added datafusion-plan and datafusion-dispatch feature aliases (no-op
  forward stubs gating audit_from_plan and parsed_query_to_plan helpers)
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6133eb2222

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +189 to +193
// For now we only have rls + audit; trivial 2-plugin case.
// Full topo sort can land in a follow-up PR.
// Order: rls → audit (audit logs the rewritten plan, so RLS must run first).
// TODO: real topo sort via depends_on() once N>2 plugins.
Ok(())
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Enforce plugin prerequisites during registry sealing

MembraneRegistry::seal() currently always returns Ok(()), so misconfigured plugin wiring is never rejected at boot despite the new plugin-handshake contract. In configurations where audit is installed without its required RLS dependency (or future plugin dependency edges), startup will incorrectly succeed and the system will run without the intended safety checks; this contradicts the method’s documented behavior and makes configuration errors silent.

Useful? React with 👍 / 👎.

@AdaWorldAPI AdaWorldAPI merged commit 63c3f5b into main Apr 29, 2026
1 of 5 checks passed
AdaWorldAPI added a commit that referenced this pull request Apr 30, 2026
Sprint C agent (PR #311) flagged five staleness items in the vision
doc that were out of its §7-only scope. Closing the debt now:

  Header           DRAFT - pending review (2026-04-28)
                   -> Status: F1 parity shipped 2026-04-30. F1
                      latency benchmark not yet started. F2 is a
                      posture, not a delivery.

  §2 anchor        as of 2026-04-28
                   -> as of 2026-04-30 (post-F1 parity ship)

  §2 latency cell  Designed to match; F1 numbers (forward tense)
                   -> Designed to match; benchmark pending

  §2 caveat        F1 publishes the first numbers (forward tense)
                   -> F1 parity has shipped (correctness); the
                      separately-scoped F1 latency benchmark has
                      not been started. Distinguishes the two
                      sub-deliverables explicitly.

  §3 F1            We stand up a Foundry instance... (forward)
                   -> Shipped 2026-04-30. Cross-link to §7's
                      as-shipped architecture.

  §3 F2            gated upstream by lance-graph PR-1 / PR-2
                   -> lance-graph PR #278 + #280 + #284 (RLS) and
                      PR #278 + #302 (audit). Status today:
                      lance-graph in production; medcare-rs
                      adopter not yet open. Posture, not
                      delivery.

  §3 F3            gated upstream by lance-graph PR-4
                   -> lance-graph PR #278 + #280 (parser +
                      hardening). Status today: parser stub on
                      lance-graph main; medcare-rs adopter is
                      future round-2 work.

  §4               benchmark harness lands as part of F1
                   F1 numbers are published (both forward tense)
                   -> F1 parity (correctness) shipped; F1 latency
                      benchmarking has not been started. The two
                      are separately-scoped F1 sub-deliverables.

What this PR does NOT touch:
  - F4, F5, §5 (risks), §6 (NOT promising), §7 (next deliverable
    just landed in PR #311 - clean already).
  - The vision doc's tone rule. Every change cites a concrete PR
    number or file path; no marketing language introduced.
  - Performance numbers. None claimed; the §4 'do not quote
    unbenchmarked numbers' rule is preserved verbatim.

Diff: +41 / -26 across 1 file. Markdown renders cleanly.

Cross-link: PR #311 (the §7 fix that motivated this cleanup).
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.

2 participants