Skip to content

Rebuild - #60

Merged
qianmoQ merged 15 commits into
devfrom
rebuild
Oct 2, 2026
Merged

qianmoQ merged 15 commits into
devfrom
rebuild

Conversation

@qianmoQ

@qianmoQ qianmoQ commented Oct 2, 2026

Copy link
Copy Markdown
Member

Changelog category (leave one)

  • New Feature
  • Bug Fix
  • Documentation (changelog entry is not required)
  • Other

Changelog entry (Details of this change)

If there is an issue connection, write it to the end of the question
e.g: issue-7
Please delete this information when submitting

  • e.g: Support XXXXX

Affected version

  • e.g: latest version

qianmoQ added 15 commits October 1, 2026 07:03
The role, menu and HTTP method pages called endpoints the rebuilt server
does not have, so nothing they configured took effect. Remove them from the
navigation, the router and the page permission manifest, together with the
components and helpers only they used and their messages. Roles come back
with the console's own permission model.

The dashboard no longer counts roles, menus and methods through the old
API; it shows accounts, departments, user groups and positions, and only
loads the counts of pages the user may open.
The plugin API passed its tests but not every static check: a Javadoc
summary ended in a colon, a test kept an unused import, and PMD flagged
a null assignment, an unused parameter, an allocation in a loop and two
intended designs (a Comparable record and a provider interface with one
abstract method), now suppressed with the reason.
Add the authorization module with the resource catalog: applications and
their resource trees of modules, menus, pages, tabs, buttons, APIs, data
entities and fields. Each type only sits where it belongs (buttons and
tabs on pages, fields on data entities), trees are materialized paths of
at most 16 levels, codes are unique per application, and resources
declared by GrantForge itself keep their code and cannot be deleted.
The catalog is shared by all tenants: tenant administrators read it,
platform administrators change it, and every change is audited. The
console registers itself as a built-in application at start-up.

Platform administrators get a resource catalog page that switches
between applications, shows the tree with type badges, and creates,
edits, moves (buttons, a target dialog, or dragging in the tree) and
deletes resources and applications.
Every controller method now declares who may call it: @PublicEndpoint,
@AuthenticatedEndpoint or @RequirePermission with a permission code such
as system.user.read, which several endpoints may share. At start-up the
server scans its handlers and refuses to start when one declares nothing
or two things; the public routes of the security configuration are
tested against the declarations.

The scan keeps an API catalog in step with the code: every permission
becomes a built-in API resource below a built-in API module of the
console, ready to be granted, and every endpoint is recorded with its
access. Endpoints that appeared, changed their access or went away are
marked until a platform administrator confirms them, which is audited.
The OpenAPI document publishes each operation's access as x-permission.

The console gets an API catalog page with counts, filters by text,
access and state, and confirmation of the pending changes.
Menus, pages, tabs and buttons can now depend on APIs, pages, tabs and
buttons of the same application, as required or optional. Dependencies
never form a cycle: a new one that would is refused, and a resource others
still need cannot be deleted, while deleting a resource removes its own
dependencies. Dependencies declared by GrantForge itself cannot be removed
by hand. A dependency graph answers what a set of resources requires,
transitively, for deriving grants later. Every change is audited.

The resource catalog page shows, for each resource, what it needs and
what needs it; platform administrators add dependencies, switch them
between required and optional and remove them, and a drawing lays out
everything around a resource: what needs it on the left, what it needs,
also indirectly, on the right.
The web console's permission manifest (src/permissions/manifest.json)
now lists its modules, pages and buttons, each with the API permissions
and other entries it needs; the console derives its page permissions
from it. The server packages the same file and, at start-up and right
after the API catalog, creates every entry as a built-in resource,
refreshes names and routes, and keeps the declared dependencies exactly
as listed, taking over manual ones the manifest now declares. A manifest
that repeats codes, names unknown permissions or resources, places an
entry where its type does not fit or closes a cycle stops the start.

Built-in resources carry the message key of their name, so the resource
catalog shows the console's own pages and buttons in the user's
language. The message check counts keys named by the manifest.
Tenant administrators create, edit, copy, enable, disable and delete the
roles of their tenant; codes are unique per tenant and every change is
audited. Every tenant gets system roles: a tenant administrator role, and
in the platform tenant also a platform administrator role. They are
created when a tenant is created (identity now announces new tenants once
committed) and at start-up for existing tenants; they cannot be changed,
disabled or deleted, only copied.

The console gets a roles page with search, system roles named in the
user's language, and dialogs to create, edit and copy roles; the page and
its buttons are declared in the permission manifest.
Tenant administrators give roles to accounts, user groups, departments
(optionally including their sub-departments) and positions, for a while
or for good, change those terms and take roles away; every change is
audited. An account's roles are worked out from its direct assignments
and those of its groups, departments, parent departments and positions,
within their validity and only while the role is enabled.

System accounts get their tenant's system roles, when a tenant is created
and at start-up, and keep them; only platform administrators give the
platform administrator role. Identity now announces deleted accounts,
groups, departments and positions, and their assignments go with them;
deleting a role removes its assignments.

The roles page opens who has a role, with pickers for each kind of
subject, validity dates and the sub-department option; the user list
shows each account's roles and how it has them.
Roles now allow or deny menus, pages, tabs, buttons and APIs, optionally
until a time. Only explicit grants are stored; the rest is derived and
explained: denials win and reach everything below, an allowed resource
makes its ancestors visible and implies what it requires, transitively,
and every derived state names its reasons. System roles have whole
modules (the tenant administrator the access-control module, the
platform administrator also the platform module) and cannot be changed;
platform resources can only be granted in the platform tenant. Copying a
role copies its grants, deleting a role removes them, and a granted
resource cannot be deleted from the catalog. Changes are audited.

The roles page gets a grant matrix: the application's resource tree with
allow and deny choices, each choice previewed by the server so derived
states and their reasons show at once, and the changes saved together.
The console now asks the server what the signed-in user may reach, and the
server answers from every effective role: denials win and reach down, allowed
resources make their ancestors visible and bring along what they require, and
system roles cover their modules. Administrators can no longer hand out a role
or grant a resource beyond their own permissions.

Property tests check the derivation laws on random catalogs.
Every API that declares a permission now checks it against the caller's
current permissions, worked out from their roles on each call, so a changed
grant, assignment or role status applies to the very next request. Handlers
without a declaration are refused.

The identity services no longer reserve administration for the tenant's
built-in account: any role granted the matching permission may use them. A
matrix test calls every guarded API anonymously, without roles, as tenant
administrator and as platform administrator.
Menus, pages and every action button now follow the signed-in user's
permissions: v-permission hides a button (or disables it with :disable) and
PermissionGuard shows content only with a resource. Answers to guarded calls
report the version of the caller's permissions, and the console reloads them
when it changes, so a revoked role disappears from the console at the next
call.

The full-stack test signs in a user holding one role and checks the menus and
buttons they see, the pages they are kept from, and an API call refused with
403.
check_permission_manifest.py keeps the console's permission manifest
consistent: entries nest and are named as the server expects, the APIs they
need exist in the API contract, their requirements exist and form no cycle,
every API permission is needed by a page or button or listed as granted
directly with a reason, page routes exist in the router, and every resource
or permission code the console quotes exists.

Also adds the unit test of the permission guard that the test mapping check
asks for.
A check-up of an application finds what gives nothing or cannot work: grants
of disabled resources, of retired APIs or past their expiry (in every
tenant), buttons whose dependencies reach no API in service, APIs nothing
needs and no role is granted, and dependencies on disabled resources or
retired APIs. The new platform page lists the findings by issue; the check-up
only reads.
The role, grant, assignment and catalog services, and tenant management, no
longer reserve their work for each tenant's built-in administrator account:
whoever holds the permission may do it, as the API checks. What remains are
the tenant boundaries: only accounts of the platform tenant change the shared
catalog and manage tenants, and only holders of the platform administrator
role give, change or remove it.

A page shown because a button below it is allowed now also works: it brings
along the APIs it requires, so allowing only the create-role button lets the
holder list roles too.
}
function field(label: string) {
const owner = [...document.querySelectorAll<HTMLLabelElement>('dialog[open] label')]
.find(item => item.textContent?.replace('*', '').trim() === label)
return found as HTMLButtonElement
}
async function fill(label: string, value: string) {
const owner = [...document.querySelectorAll<HTMLLabelElement>('dialog[open] label')].find(item => item.textContent?.replace('*', '').trim() === label)
await flushPromises()
}
const field = (label: string) => {
const owner = [...document.querySelectorAll<HTMLLabelElement>('dialog[open] label')].find(item => item.textContent?.replace('*', '').trim() === label)
@qianmoQ
qianmoQ merged commit f3a67c3 into dev Oct 2, 2026
48 of 54 checks passed
@qianmoQ
qianmoQ deleted the rebuild branch October 2, 2026 03:10
@github-actions

github-actions Bot commented Oct 2, 2026

Copy link
Copy Markdown

Dependency Review

The following issues were found:
  • ✅ 0 vulnerable package(s)
  • ❌ 2 package(s) with incompatible licenses
  • ✅ 0 package(s) with invalid SPDX license definitions
  • ⚠️ 7 package(s) with unknown licenses.
See the Details below.

License Issues

core/grantforge-authz/pom.xml

PackageVersionLicenseIssue Type
net.jqwik:jqwikLicenseRef-github-NOASSERTIONIncompatible License
org.devlive.grantforge:grantforge-auditNullUnknown License
org.devlive.grantforge:grantforge-commonNullUnknown License
org.devlive.grantforge:grantforge-identityNullUnknown License
org.devlive.grantforge:grantforge-persistenceNullUnknown License
org.devlive.grantforge:grantforge-test-supportNullUnknown License

pom.xml

PackageVersionLicenseIssue Type
net.jqwik:jqwik1.9.3LicenseRef-github-NOASSERTIONIncompatible License
org.devlive.grantforge:grantforge-authz2026.0.0NullUnknown License

core/grantforge-server/pom.xml

PackageVersionLicenseIssue Type
org.devlive.grantforge:grantforge-authzNullUnknown License
Allowed Licenses: MIT, MIT-0, Apache-2.0, BSD-2-Clause, BSD-3-Clause, ISC, 0BSD, CC0-1.0, CC-BY-4.0, Unlicense, BlueOak-1.0.0, Python-2.0, EPL-1.0, EPL-2.0, MPL-2.0, LGPL-2.1-only, LGPL-2.1-or-later
Excluded from license check: pkg:maven/com.oracle.database.jdbc/ojdbc11, pkg:maven/com.oracle.database.jdbc/ucp11, pkg:maven/com.mysql/mysql-connector-j

OpenSSF Scorecard

Scorecard details
PackageVersionScoreDetails
maven/net.jqwik:jqwik UnknownUnknown
maven/org.devlive.grantforge:grantforge-audit UnknownUnknown
maven/org.devlive.grantforge:grantforge-common UnknownUnknown
maven/org.devlive.grantforge:grantforge-identity UnknownUnknown
maven/org.devlive.grantforge:grantforge-persistence UnknownUnknown
maven/org.devlive.grantforge:grantforge-test-support UnknownUnknown
maven/org.springframework.boot:spring-boot-starter-data-jpa-test UnknownUnknown
maven/org.springframework.boot:spring-boot-starter-liquibase UnknownUnknown
maven/org.springframework.boot:spring-boot-starter-test UnknownUnknown
maven/org.devlive.grantforge:grantforge-authz UnknownUnknown
maven/net.jqwik:jqwik 1.9.3 UnknownUnknown
maven/org.devlive.grantforge:grantforge-authz 2026.0.0 UnknownUnknown

Scanned Files

  • core/grantforge-authz/pom.xml
  • core/grantforge-server/pom.xml
  • pom.xml

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