Skip to content

Emit the views ACL section - #62

Merged
gmr merged 1 commit into
mainfrom
fix/views-acl-section
Aug 31, 2026
Merged

gmr merged 1 commit into
mainfrom
fix/views-acl-section

Conversation

@gmr

@gmr gmr commented Aug 31, 2026

Copy link
Copy Markdown
Owner

Summary

schemata/acls.yml:134 accepts a views: key and models::Acls
carries the field, but src/build/acls.rs's SECTIONS never listed it,
so a hand-authored view grant validated, loaded, and was then silently
discarded. Same failure mode as the role membership gap fixed in #58.

Fixes #60.

Problem

Three places have to agree on a section name and only two did:

  • schemata/acls.yml:134 defines views: (schema.name[SELECT|ALL])
  • src/models/roles.rs:41 carries pub views: Option<Map<String, Value>>
  • SECTIONS had 13 entries and no views among them

Nothing surfaced it. section()'s unreachable! fires only for a name
present in SECTIONS, and views was absent from SECTIONS entirely,
so the field was never read — no error, no warning, no entry.

Solution

Emit it as part of the tables: section rather than as a section of
its own, which is the part worth reviewing.

PostgreSQL grants on views with TABLE syntax — GRANT SELECT ON VIEW x
is not valid SQL — which is why pull already routes view grants to
tables: via section_key(). So views: is an alternate spelling of
the same statement, not a different statement. A dedicated SECTIONS
entry would emit correct SQL but give a view named under both keys two
ACL entries carrying the same TABLE <name> tag; feeding both fields
into one bucket coalesces them into the single entry the object
warrants.

The mechanism is a coalesced() companion to the existing section():

fn coalesced<'a>(acls: &'a Acls, key: &str) -> Option<&'a Map<String, Value>> {
    match key {
        "tables" => acls.views.as_ref(),
        _ => None,
    }
}

RELATIONS already covers Table/View/MaterializedView, so
dependency resolution and entry ownership needed no change.

I did not take option 2 from the issue (delete views: from the schema).
The schemata are a contract carried over from Python unchanged, and
additionalProperties: false makes removing a key breaking for any
project that hand-authored it — a much larger blast radius than the bug.

Tests

  • emits_grants_from_the_views_section — a views: grant reaches the
    archive as GRANT ... ON TABLE, in the view's namespace, with the
    view's owner and a dependency edge on the view's entry.
  • views_and_tables_sections_coalesce_into_one_entry — the same view
    under both keys yields exactly one ACL entry.

Renamed the test helper membership_projectproject_with (added in
#58, test-only, mechanical): it builds a project from an inventory and is
no longer membership-specific now that the views tests use it too.

Verification

  • just check (fmt-check + clippy -D warnings + test) — clean.

  • End to end against PostgreSQL 17, since unit tests here only prove
    the TOC. Built a minimal project granting SELECT under views: and
    restored it:

    $ psql -d mintest -c "select grantee, privilege_type from
        information_schema.role_table_grants
        where table_schema='test' and table_name='active'"
    reader|SELECT     <- the views: grant, on a real database
    

    Restore completed with no errors.

  • just docs not run — mkdocs is not installed in this environment. The
    docs change is one bullet in an existing list with no new links or nav
    entries, so --strict has nothing new to resolve, but CI should
    confirm.

Summary by CodeRabbit

  • New Features

    • View access grants can now be declared under either tables or views.
    • Table and view grants are combined into a single table access entry.
    • View permissions are preserved under tables when configurations are pulled.
  • Documentation

    • Updated project format documentation to describe the supported view grant declarations.

schemata/acls.yml accepts a views: key and models::Acls carries the
field, but build's SECTIONS never listed it, so a hand-authored view
grant validated, loaded, and was then silently discarded — the same
failure mode as the role membership gap fixed in #58. There is no
panic to surface it: section()'s unreachable! fires only for a name
present in SECTIONS, and views was absent from SECTIONS entirely, so
the field was simply never read.

Emit it as part of the tables section rather than as a section of its
own. PostgreSQL grants on views with TABLE syntax — which is why pull
already writes view grants under tables: — so views: is a spelling of
the same statement, not a different one. A dedicated SECTIONS entry
would give a view named under both keys two ACL entries carrying the
same tag; feeding both fields into one bucket coalesces them into the
single entry the object warrants.

Verified end to end: a project granting SELECT under views: restores
into PostgreSQL 17 with the privilege present on the view.

Fixes #60

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 31, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: fd6cbb4f-9ec8-49ce-8dfd-7e60f9c6bb3f

📥 Commits

Reviewing files that changed from the base of the PR and between 34363e6 and f965084.

📒 Files selected for processing (2)
  • docs/project-format.md
  • src/build/acls.rs

Included review availability: 8 reviews are currently available. Your included PR review attempts over the past 7 days set your current allowance at 10 reviews per hour.


📝 Walkthrough

Walkthrough

The ACL builder now emits grants declared under views: as TABLE ACL entries. It coalesces matching views: and tables: grants. Tests and project-format documentation cover the behavior.

Changes

View ACL emission

Layer / File(s) Summary
ACL coalescing implementation
src/build/acls.rs
The ACL collector maps views into the tables output section and combines both sources before generating statements.
ACL emission tests and documentation
src/build/acls.rs, docs/project-format.md
Tests cover view-only and combined grants. Membership tests use a generalized project fixture. Documentation describes both declaration locations and pull output.
Estimated code review effort: 2 (Simple) ~10 minutes

Merge Risk: ⚪ Minimal · up to f9650

The change adds support for emitting view grants through the existing table-grant path and reports passing checks; no actionable merge-blocking risk remains beyond normal review.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 16 functions across 1 files. (1 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the primary change: emitting grants from the views ACL section.
Linked Issues check ✅ Passed The PR satisfies issue #60 by emitting hand-authored views grants through the existing tables ACL section with PostgreSQL TABLE syntax. It also coalesces table and view grants and adds tests that prev…
Out of Scope Changes check ✅ Passed The documentation updates, ACL tests, and generalized project fixture support the linked issue and the implementation. No unrelated code changes are identified.
Full details: Linked Issues check

Explanation

The PR satisfies issue #60 by emitting hand-authored views grants through the existing tables ACL section with PostgreSQL TABLE syntax. It also coalesces table and view grants and adds tests that prevent silent loss.

Full details: Docstring Coverage

Explanation

Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 16 functions across 1 files. (1 skipped: 1 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/views-acl-section

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

@gmr
gmr merged commit 7211bfb into main Aug 31, 2026
2 checks passed
@gmr
gmr deleted the fix/views-acl-section branch August 31, 2026 16:28
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.

build: views ACL section is accepted by the schema but never emitted

1 participant