The organisation allows only its own actions, so the release job failed at
startup. Checkout uses git with the job token and Node comes from the official
tarball verified against its SHA-256. A manual dispatch builds an existing tag,
so a tag cut before this change is released without moving it.
Steps 1, 2, 4 and 5 called get_comprehensive_roles() for every row of
morbac.rules (and org_in_scope() per row), so a decision cost grew with
every tenant's rules: ~240 ms with 2376 rules across 27 orgs. Roles are now
resolved once per org where the user can hold one and that has a rule for
the request, rules are read through those (org, role) pairs, and
org_in_scope() runs once per (org, scope) pair. Decisions are unchanged.
Release 1.0.1 with the 1.0.0 -> 1.0.1 upgrade script. Test 17 compares
every decision with the 1.0.0 body on a seeded random fixture and checks
the cost no longer follows unrelated tenants' rules. bump_version.sh no
longer rewrites the PGXN meta-spec version.
The signed distribution is published as a GitHub release by the release
workflow on v* tags, replacing the Gitea release and its Drone pipeline.
The release body and the dist README take the homepage from META.json.
The package carries the install and upgrade scripts, built from src/ on prepack
(sql/ is not committed), with extensionSql(), upgradeScripts(), version and sqlDir.
Documents refresh_hierarchy_cache, is_rule_valid and org_in_scope, and
corrects the get_org_scope scope list which still omitted unattributed
and all.
Replaces em dashes and other typographic unicode with ASCII throughout
the schema comments, the test suite and the documentation. Comments and
prose are ASCII only.
Adds a first-class org target vocabulary shared by every rule kind: a
specific organization, unattributed (objects whose org is NULL), or all.
A role can now be granted the unassigned pile without a global rule.
- rules.scope gains 'unattributed' and 'all'
- user_rules.org_id accepts NULL to target unattributed objects
- org_in_scope partitions the classes: 'unattributed' matches only a NULL
target, tree scopes never match one
- has_permission(user, activity, view) capability probe for UI gating
- current_org_filter() parses morbac.org_ids once into org UUIDs plus the
unattributed-bucket flag (a JSON null element requests it)
- rls_check split by arity so NULL never carries two meanings:
rls_check(activity, view) for tables with no org column,
rls_check(activity, view, row_org_id[, row_user_id]) where a NULL
row_org_id means the record is unattributed
- detect_rule_conflicts is scope-aware, so rules targeting different
object sets no longer collide
Build the distribution from src/ (control, versioned SQL, META, MIT LICENSE,
PGXS Makefile, install README), checksum it, and sign an Ed25519 JWT manifest
(audience pgmorbac-release) with the verification public key attached to the
release. `npm run release` does it locally; the Drone pipeline does it on a
v* tag once the repo is Trusted with the pgmorbac_release_key + gitea_token
secrets.
Public home is now git.villains.fr/crudy/pgmorbac with docs at
pgmorbac.villains.fr. Point META.json, README and CHANGELOG links there,
drop the tracked .DS_Store, and renumber the first public release to 0.1.0
to match the published @crudy/pgmorbac package, the embedded framework SQL
and the download page. License stays MIT.