Skip to content

add authz enforcement layer - #60

Closed
aberoham wants to merge 2 commits into
NicTool:mainfrom
aberoham:feat/authz-enforcement
Closed

add authz enforcement layer#60
aberoham wants to merge 2 commits into
NicTool:mainfrom
aberoham:feat/authz-enforcement

Conversation

@aberoham

Copy link
Copy Markdown
Contributor

Spent Saturday side-eyeing Ox Alpha Free in a goal loop, a new preview model from GLM, checked by ChatGPT-5.6 Sol and Claude Fable. Here's where it got to:

v3 didn't enforce permissions yet -- now it does. A Hapi onPreHandler plugin reads app.permission metadata off route configs and runs the check before the handler fires. Keeps authz centralized instead of scattered across handlers, which is how v2's verify_obj_usage() worked conceptually.

The main pieces:

  • lib/authz.js, the engine -- group tree ownership, delegation access in both directions (record delegations grant zone read; zone edits resolve through delegated records), per-resource permission checks. Mirrors v2's check_permission() flow.
  • lib/authz-plugin.js -- wires it together, plus session revalidation against live user/group/session rows and idle expiry on every authenticated request
  • routes/delegation.js -- extracted; caps submitted permissions by the caller's own at write time
  • every route annotated with what resource/action it needs
  • you can't grant permissions you don't have, explicit-row transitions can't smuggle changes past the cap, and you can't edit your own permissions

Second pass (review fixes):

  • v2 writes root permission rows with nt_user_id=0 -- now treated like NULL everywhere
  • a record delegation scopes record collections to the delegated records instead of leaking the whole zone
  • authorization ancestry rebuilds when a group subtree moves
  • zone-record type changes rebuild the row and clear stale rdata columns
  • deleted permission rows get reused instead of accumulating duplicates

Test coverage: unit tests for the Authz class against real MySQL, integration tests via server.inject() through the full Hapi stack -- 486 tests, 485 passing, 1 skipped (pre-existing install-path test). All three v2 xt suites pass clean through the REST bridge: 5796/5796 across 14_permissions.t, 16_delegation.t, 20_permission.t.

Known gap: sql/10_nt_perm.sql still lacks a db uniqueness constraint on permission rows. Select/reuse logic stops sequential duplicates but simultaneous creates across instances could race; fixing it right needs a migration reconciling legacy NULL/0 rows first.

burning-bush-dev and others added 2 commits August 22, 2026 14:49
v3 didn't have permission enforcement yet -- this adds it. Hapi
onPreHandler plugin reads route metadata and runs checks before handlers
execute, rather than scattering permission calls inside each one.

authz.js is the engine (checkPermission, group tree walks, delegation
lookups). authz-plugin.js wires it into Hapi's request lifecycle. All
routes annotated with what they need. Delegation routes now cap submitted
permissions by the caller's own permissions at write time, which matches
how v2 does it.

Unit tests for the Authz class and integration tests via server.inject()
included. v2 xt permission tests (14_permissions, 20_permission) should
still pass -- 4892/4892 last run.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- scope directly delegated record collections to the delegated rows
  instead of exposing every record in the zone
- v2 writes root perm rows with uid=0; treat those like NULL
- rebuild authorization ancestry when a group subtree moves
- cap what a caller may grant or revoke, including explicit-row
  transitions and usable-nameserver edits; deny self-permission writes
- revalidate sessions against live user/group/session rows and idle
  expiry before trusting credentials
- rebuild record rows on type change so stale rdata columns clear;
  reuse deleted permission rows rather than accumulating duplicates

Copilot AI 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.

Pull request overview

Adds centralized authorization enforcement, live session validation, delegation management, permission capping, and scoped resource access.

Changes:

  • Introduces the Authz engine and Hapi enforcement plugin.
  • Adds delegation routes and permission-aware resource handlers.
  • Updates persistence logic and adds extensive authorization tests.

Reviewed changes

Copilot reviewed 33 out of 33 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
lib/authz.js Implements authorization rules.
lib/authz-plugin.js Enforces route permissions and sessions.
lib/authz.test.js Tests authorization behavior.
lib/delegation.js Implements delegation persistence.
lib/group/store/mysql.js Rebuilds group ancestry after moves.
lib/group/test/index.js Tests group ancestry rebuilding.
lib/permission/store/mysql.js Handles permission lookup, reuse, and updates.
lib/permission/test/index.js Tests legacy and reused permissions.
lib/session/store/mysql.js Supports distinct sessions and access timestamps.
lib/session/test/index.js Tests concurrent login sessions.
lib/user/store/mysql.js Fixes user creation and permission ownership.
lib/user/test/index.js Tests user creation behavior.
lib/zone/store/mysql.js Adds delegated zone query scopes.
lib/zone_record/store/mysql.js Adds record scopes and type-change cleanup.
lib/zone_record/test/index.js Tests record type changes.
routes/authz.test.js Adds end-to-end authorization tests.
routes/delegation.js Adds delegation HTTP endpoints.
routes/group.js Secures group routes and permission updates.
routes/group.test.js Updates authorized group fixtures.
routes/index.js Registers authorization and delegation routes.
routes/nameserver.js Secures nameserver routes.
routes/nameserver.test.js Adds nameserver permission fixtures.
routes/permission.js Secures permission CRUD operations.
routes/permission.test.js Tests self-permission restrictions.
routes/session.js Returns effective permissions with sessions.
routes/session.test.js Tests revoked-session rejection.
routes/test/permissions.js Provides route-test permission fixtures.
routes/user.js Secures user and permission mutations.
routes/user.test.js Adds user permission fixtures.
routes/zone.js Secures and scopes zone operations.
routes/zone.test.js Updates zone authorization fixtures.
routes/zone_record.js Secures and scopes record operations.
routes/zone_record.test.js Adds record permission fixtures.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread routes/user.js
Comment on lines +211 to +213
request.payload = Authz.capPermissions(userPerm, request.payload, existingPerm)

const hasPermFields = Object.keys(request.payload).some((field) => PERM_FIELDS.has(field))
Comment thread lib/authz-plugin.js
Comment on lines +102 to +116
if (
permCfg.targetCreateResource
&& request.payload?.zid !== undefined
&& await changesTarget(request, resource, action, objectId)
) {
const target = await resolveTargetGroup(request, permCfg.targetCreateResource)
const targetResult = await Authz.checkPermission(
credentials,
permCfg.targetCreateResource,
'create',
undefined,
{ targetGroupId: target?.gid, targetZoneId: target?.zid },
)
if (!targetResult.allowed) return respond(targetResult, h)
}
Comment thread lib/group/store/mysql.js
Comment on lines +169 to +173
await Mysql.execute('START TRANSACTION')
try {
const r = await update()
await this.rebuildSubgroups(id)
await Mysql.execute('COMMIT')
Comment thread lib/authz-plugin.js
Comment on lines +21 to +22
if (request.auth.isAuthenticated && !isLogin) {
const credentials = await Authz.getCurrentCredentials(request.auth.credentials)
Comment thread routes/authz.test.js
Comment on lines +14 to +18
const G_ROOT = {
id: 4200,
parent_gid: 0,
name: 'authz-root',
}
@aberoham

Copy link
Copy Markdown
Contributor Author

Superseded by #61, which contains this work rewritten across the store layer plus the fixes from its copilot review (self permission edits, cross-zone record moves, session activity refresh).

@aberoham aberoham closed this Aug 25, 2026
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.

3 participants