Skip to content
bitzorcas
中EN

Guide

Menu Security, Testing, Operations, and Commercial GA

Authentication and authorization boundaries, global blast radius, test evidence, diagnostics, release checklist, and source-grounded commercial GA gaps.

Last updated

Menu has a clear owner, generated endpoints, permission catalog, dual-ORM store, and cross-instance invalidation skeleton. Tree integrity, change atomicity, audit, and recovery are not yet commercial-GA grade.

1. Security model

JWT authentication

Menu management endpoints

menus.menu.* resource authorization

navigation endpoint

role-to-module visibility

global SysModule mutation

display decision only

target endpoint authorization

Management endpoints authenticate and require create/update/delete/view. Navigation authenticates and filters by role-module visibility, without a Menu management permission.

2. Global blast radius

SysModule is not tenant-scoped. Every management write changes the platform-wide catalog and removes the global menu cache tag. Role grants are tenant-owned, but structure, labels, links, and enabled flags are shared.

Menu management must therefore be treated as a high-risk platform permission, not ordinary tenant configuration.

3. Display-filter boundary

Authorize every target endpoint independently
// ① Navigation decides only whether to show an entry to this user.
var navigation = await menus.GetNavigationAsync(currentUser, cancellationToken);
// ② The target command declares its own resource and action.
public sealed record ApproveInvoice(string InvoiceId)
: ICommand<Result>, IAuthorizedRequest
{
public ResourceDescriptor Resource { get; } = new("billing", "invoice");
public AuthorizationAction Action { get; } = AuthorizationAction.Approve;
}
// ③ A manually constructed URL still reaches the authorization pipeline.

Never treat LinkUrl as trusted policy input or node presence as backend authorization.

4. Admin-shortcut risk

Any case-insensitive role name admin receives all enabled catalog rows. This is an application convention, not an explicit permission grant. IdP mapping or tenant-custom role names could trigger it unexpectedly.

GA should choose an unforgeable platform claim, explicit super-admin capability, or a normal Authorization decision, then fix casing, tenant, and audit semantics in tests.

Current writes do not validate LinkUrl scheme, host, relative form, open redirects, or values such as javascript:. Icon is also unrestricted. A client must encode values and use an allowlist; the safer server rule is an internal relative route.

Render Name and Description as text, never untrusted HTML.

6. Existing automated evidence

TestWhat it currently proves
MenuQueryHandlerTestsDetail success and not-found
MenuInfrastructureArchitectureTestsORM neutrality, Store-only queries, fail-closed adapter
AuthorizationMenuPersistenceOwnershipArchitectureTestsownership, narrow ports, generated model/seed manifests, migration shape
IdentitySeedDataTestsmenu/permission seed references and asset rules
FeatureDefinitionSeedStepTestsfeature assets resolve referenced modules
PortRepositoryParityTestsequal Store behavior on SqlSugar and EF Core
ApiShellHostBuildSmokeTestsunavailable Store without a database

This evidence does not cover tree algorithms or write business rules.

7. Required test pyramid

many unit tests: visibility/tree/validators

integration: transaction/index/cache/outbox

contract: generated HTTP/auth/problem details

few E2E: multi-tenant/multi-instance/admin

Fix deterministic algorithms with fast tests, then prove infrastructure behavior with real databases and two API instances.

8. Operational diagnosis

When a menu is missing, inspect in order:

  1. authentication success;
  2. expected role names in ICurrentUser.User.Roles;
  3. module Codes returned by Authorization;
  4. exact SysModule Code match;
  5. Enabled/non-deleted target and ancestors;
  6. root reachability of every ancestor;
  7. IsMenu=true along the navigation path;
  8. stale cache on the current instance.

9. Cache diagnosis

Terminal window
# Find sync handling and invalidation failures.
rg -n "Menu cache invalidated|Failed to invalidate menu cache" ./logs
# Confirm tag, TTL, and event resource in source.
rg -n "MenuCacheTags|CachePolicy.Medium|LocalResourceTypes.Cache" src/Platform/Menu -g '*.cs'
# Database diagnosis must inspect Code, ParentId, Enabled, IsMenu, and IsDeleted together.

The consumer suppresses errors, so message consumption alone does not prove cache removal.

10. Integrity scan

A production scanner should report blank/duplicate Code, blank Name, orphan ParentId, self-parenting, cycles, excessive depth, unreachable enabled nodes, menu children under non-menu parents, duplicate sibling OrderSort, unsafe LinkUrl, and grants referencing absent Codes.

It should report and produce a reviewed repair plan, not silently rewrite the global catalog.

11. Release checklist

  • Back up SysModule and role-module-permission relations.
  • Compare seed assets with database state.
  • Verify 401/403/success for all nine endpoints.
  • Run parity on every supported ORM.
  • Verify broadcast invalidation with two API instances.
  • Simulate notifier and cache failures.
  • Exercise deep, cyclic, and orphan data.
  • Restrict links to allowed internal routes.
  • Prepare Code migration and rollback scripts.
  • Smoke-test normal, role-less, and super-admin users after release.

12. Commercial GA gaps

In priority order:

  1. transactional tree validators and defensive cycle/depth reads;
  2. atomic reparent, cascade delete, and deterministic ordering;
  3. immutable Code or an explicit migration workflow;
  4. full URL/Name/Icon/Scope validation;
  5. database-to-cache outbox and retry;
  6. ResourceId filtering and failed-event delivery;
  7. optimistic concurrency and affected-row checks;
  8. platform management audit, approval, and rollback;
  9. a product decision for tenant overrides/localization;
  10. consumer contracts, dual-instance tests, and fault injection gates.

The Architecture Hub Menu GA backlog contains concrete work items. This page describes current implementation and acceptance direction only.

13. Deployment judgment

The module can be used in a controlled internal setting with trusted platform administrators, controlled seeds, shallow acyclic data, and a tolerated 15-minute cache fallback. Do not claim GA for tenant self-service, strict audit, zero staleness, or complex visual tree editing yet.

14. Global sweeps

Terminal window
# Current automated evidence.
rg -n "Menu" tests -g '*.cs'
# Cycle, transaction, outbox, and audit gaps; expect no substantive Menu matches.
rg -n "visited|MaxDepth|UnitOfWork|Outbox|Audit" src/Platform/Menu -g '*.cs'
# Every generated endpoint and resource-authorized request.
rg -n "GenerateEndpoint|IAuthorizedRequest" src/Platform/Menu -g '*.cs'

Module overview · Management and cache

100%

Scroll or use controls to zoom · drag when enlarged · double-click for 100% / 200%