Skip to content

refactor(meta): migrate Auth/loader/codegen readers to effective ModelId - #247

Merged
buke merged 6 commits into
mainfrom
feat/meta-effective-dual-store-eds3
Aug 5, 2026
Merged

refactor(meta): migrate Auth/loader/codegen readers to effective ModelId#247
buke merged 6 commits into
mainfrom
feat/meta-effective-dual-store-eds3

Conversation

@buke

@buke buke commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

User description

Summary

  • Add LookupEffectiveModel and wire loader / translated_seed / bootstrap to resolve (application, name) without tip Order.
  • Auth MethodAccess / RecordRule / FieldRule / PermissionState use a shared single-effective resolver; FieldRule drops multi-id IN workaround.
  • RemapACLToEffectiveModelIDs remaps auth ACL meta_model_id / field / orphan service FKs; runs after dual-store migrate and full recompute.
  • Codegen and webBuilder read effective-only rows (module_id empty); drop production in-memory IMD merge.
  • Export TS MetaModelRaw (+ raw field/service/decorator/argument/parameter/type_parameter) facades.

Test plan

  • go test ./pkg/meta/ ./internal/module/evolution/data/ ./internal/module/artifact/generate/ ./internal/bootstrap/service/ ./internal/module/artifact/build/web/ -count=1
  • ./choysum test unit auth --be (176 ok)
  • CI green on this PR
  • Optional wipe/reinstall: ACL seeds resolve via effective ids; FieldRule no longer depends on multi-row IMD

Notes

  • ModelData sqlModelId tip / SavedFilter remain EDS-4.
  • Wipe+reseed still valid; remap helper covers upgrade DBs with historical ACL FKs.

Made with Cursor


PR Type

Enhancement, Tests


Description

  • Migrate Go loader and codegen to effective models

  • Add ACL remapping and effective lookups in Go

  • Refactor Auth module evaluation to effective model IDs

  • Export TS raw metadata facades and update tests


File Walkthrough

Relevant files
Refactoring
6 files
coordinator.go
Use LookupEffectiveModel for auth User bootstrap resolution
+4/-2     
generator.go
Load effective-only model rows in gRPC generator                 
+5/-57   
loader.go
Migrate data loader queries to LookupEffectiveModel           
+8/-16   
_user_field_rule_eval.ts
Refactor FieldRule evaluation to single effective model ID
+20/-58 
_user_method_access.ts
Use effective model resolver in method access evaluation 
+3/-17   
_user_record_rule_eval.ts
Use resolveEffectiveModelRow in record rule evaluation     
+4/-18   
Enhancement
11 files
webBuilder.go
Filter web builder model dependencies to effective projections
+1/-6     
lookup_effective.go
Add LookupEffectiveModel helper for single live projections
+68/-0   
acl_remap.go
Add RemapACLToEffectiveModelIDs for auth rule foreign keys
+210/-0 
dual_store_migrate.go
Trigger RemapACLToEffectiveModelIDs after dual-store migration and
recompute
+9/-3     
_resolve_effective_model.ts
Add TypeScript helper to resolve effective model and app IDs
+70/-0   
_user_permission_state_acl.ts
Deduplicate ACL model search results by application and name
+30/-9   
model_raw.ts
Add MetaModelRaw declaration facade model                               
+82/-0   
field_raw.ts
Add MetaFieldRaw declaration facade model                               
+36/-0   
service_raw.ts
Add MetaServiceRaw declaration facade model                           
+52/-0   
decorator_raw.ts
Add MetaDecoratorRaw declaration facade model                       
+34/-0   
index.ts
Export raw metadata facade models                                               
+7/-0     
Tests
3 files
lookup_effective_test.go
Add unit tests for LookupEffectiveModel function                 
+61/-0   
acl_remap_test.go
Add unit tests for RemapACLToEffectiveModelIDs                     
+133/-0 
field_rule.test.ts
Update Auth field rule unit tests to resolve effective model ID
+3/-19   
Additional files
15 files
generator_test.go +39/-95 
translated_seed.go +3/-5     
authz_context_memoization.test.ts +2/-12   
authz_mutation_crud_coverage.test.ts +2/-14   
bootstrap_gift_pack.test.ts +4/-26   
check_method_access_company_scope.test.ts +3/-18   
check_method_access_diagnostics.test.ts +2/-7     
permission_state.test.ts +3/-16   
record_rule.test.ts +3/-17   
record_rule_eval_edges.test.ts +2/-10   
role_ui_resource_sync.test.ts +3/-21   
_owner_auth_test_fixtures.ts +2/-11   
argument_raw.ts +21/-0   
parameter_raw.ts +18/-0   
type_parameter_raw.ts +18/-0   

Summary by CodeRabbit

  • Bug Fixes

    • Improved consistency when resolving models across administration, authorization, data loading, and artifact generation.
    • Prevented outdated or declaration-only model records from being selected.
    • Automatically remapped access-control references to current effective models, fields, and services.
    • Improved handling of missing models and repeated migration operations.
  • New Features

    • Added support for reading raw metadata definitions, including models, fields, services, decorators, arguments, parameters, and type parameters.

- Resolve meta_model via LookupEffectiveModel (no tip Order) in loader, bootstrap, and dual-store ACL remap after migrate/recompute.

- Point Auth FieldRule/RecordRule/MethodAccess at a single effective ModelId and add MetaModelRaw TS facades for declaration reads.

- Load codegen/webBuilder from effective-only rows (empty module_id) without in-memory IMD merge.

Co-authored-by: Cursor <cursoragent@cursor.com>
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR centralizes effective-model lookup, updates metadata and authorization consumers, excludes declaration shells from artifact generation, adds raw metadata entities, and remaps ACL references after effective-model migrations.

Changes

Effective model resolution

Layer / File(s) Summary
Effective lookup and Go integrations
pkg/meta/lookup_effective.go, internal/bootstrap/..., internal/module/...
Effective lookup selects live rows. Go consumers and artifact generation use effective models.
Authentication effective-ID resolution
modules/auth/service/models/*, modules/auth/service/tests/*, modules/document/...
Authentication metadata, rule evaluation, permission loading, and test helpers use shared effective application and model resolvers.

ACL reference remapping

Layer / File(s) Summary
ACL remapping workflow
pkg/meta/acl_remap.go, pkg/meta/acl_remap_test.go, pkg/meta/acl_remap_coverage_test.go, pkg/meta/dual_store_migrate.go
Model, field-rule, and method-service ACL references are remapped to effective models after migration and recomputation. Tests cover remapping and error propagation.

Raw metadata model entities

Layer / File(s) Summary
Raw metadata entity contracts
modules/meta/service/models/*_raw.ts, modules/meta/service/models/index.ts
Raw metadata entities define tables, localized fields, relationships, and barrel exports.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant DualStoreMigration
  participant RemapACLToEffectiveModelIDs
  participant MetadataDatabase
  participant AuthTables
  DualStoreMigration->>RemapACLToEffectiveModelIDs: invoke after effective unique index
  RemapACLToEffectiveModelIDs->>MetadataDatabase: resolve effective models, fields, and services
  RemapACLToEffectiveModelIDs->>AuthTables: update model, field, and service references
  AuthTables-->>DualStoreMigration: return remapping result
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 26.92% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title accurately summarizes the main change: migrating Auth, loader, and codegen readers to use effective ModelId resolution instead of direct model queries.
Description check ✅ Passed The description provides a clear summary of changes, test plan with results, and notes about remaining work. All required sections are present and substantially complete.
✨ 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 feat/meta-effective-dual-store-eds3

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

@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 2 🔵🔵⚪⚪⚪
🧪 PR contains tests
🔒 No security concerns identified
⚡ No major issues detected

@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
Fix invalid DB field access on session

**txScope.Session() returns gorm.DB directly. Accessing .DB on gorm.DB is invalid
and will fail to compile. Pass txScope.Session() directly.

internal/bootstrap/service/coordinator.go [653]

-		lookedUp, err := meta.LookupEffectiveModel(txScope.Session().DB, "auth", "User")
+		lookedUp, err := meta.LookupEffectiveModel(txScope.Session(), "auth", "User")
Suggestion importance[1-10]: 9

__

Why: txScope.Session() returns *gorm.DB, which does not have a .DB field. Accessing .DB causes a compilation error, so txScope.Session() should be passed directly to meta.LookupEffectiveModel.

High

@codecov

codecov Bot commented Aug 5, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ All tests successful. No failed tests found.

📢 Thoughts on this report? Let us know!

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

🧹 Nitpick comments (3)
pkg/meta/acl_remap.go (2)

98-98: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove the unused oldToEffective parameter.

remapFieldRuleFieldIDs never reads oldToEffective. Line 144 discards it inside the loop on every iteration. This is a dead artifact. Remove the parameter and update the call site at line 92.

♻️ Proposed cleanup
-func remapFieldRuleFieldIDs(db *gorm.DB, oldToEffective map[string]string) error {
+func remapFieldRuleFieldIDs(db *gorm.DB) error {
 		}
-		_ = oldToEffective // retained for call-site clarity
 	}

Call site at line 92:

-	if err := remapFieldRuleFieldIDs(db, oldToEffective); err != nil {
+	if err := remapFieldRuleFieldIDs(db); err != nil {

Also applies to: 144-144

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/meta/acl_remap.go` at line 98, Remove the unused oldToEffective parameter
from remapFieldRuleFieldIDs and update its call site accordingly. Delete the
loop statement that discards oldToEffective, while preserving the function’s
existing remapping behavior.

73-95: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Wrap the ACL rewrites in one transaction.

The three model-ID updates, the field-rule remap, and the service remap run as separate statements outside a transaction. If a later statement fails, the ACL tables keep a partial mapping. The function is idempotent, so a re-run repairs the state, but only if an operator notices the error.

Wrap the mutation phase in db.Transaction so the ACL rewrite commits atomically.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/meta/acl_remap.go` around lines 73 - 95, Wrap the entire mutation phase
in pkg/meta/acl_remap.go’s visible remap flow, including the table updates,
remapFieldRuleFieldIDs, and remapOrphanServices, in a single db.Transaction
callback. Return each error from the callback so any failure rolls back all ACL
changes, and only return the transaction result after it commits successfully.
pkg/meta/acl_remap_test.go (1)

126-132: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Strengthen the idempotency check and cover the service remap path.

Two gaps:

  1. The second RemapACLToEffectiveModelIDs call only asserts that no error occurs. Re-read meta_model_id and meta_field_id after the second call to prove the values stay at eff-id and new-field.
  2. remapOrphanServices is never exercised. The seeded auth_role_method_access row has no meta_service_id, so the whole function returns after the first row filter. Seed a Service under shell-id and a matching Service under eff-id, set meta_service_id on ma1, then assert the remap to the effective service ID.
💚 Proposed idempotency assertion
 	// Idempotent.
 	if err := RemapACLToEffectiveModelIDs(db); err != nil {
 		t.Fatalf("second RemapACL: %v", err)
 	}
+	var rr2, fr2Model, fr2Field string
+	if err := db.Raw(`SELECT meta_model_id FROM auth_role_record_rule WHERE id = ?`, "rr1").Scan(&rr2).Error; err != nil {
+		t.Fatalf("re-read rr: %v", err)
+	}
+	if err := db.Raw(`SELECT meta_model_id, meta_field_id FROM auth_role_field_rule WHERE id = ?`, "fr1").Row().Scan(&fr2Model, &fr2Field); err != nil {
+		t.Fatalf("re-read fr: %v", err)
+	}
+	if rr2 != "eff-id" || fr2Model != "eff-id" || fr2Field != "new-field" {
+		t.Fatalf("second run changed values: rr=%q frModel=%q frField=%q", rr2, fr2Model, fr2Field)
+	}
 	if err := RemapACLToEffectiveModelIDs(nil); err == nil {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/meta/acl_remap_test.go` around lines 126 - 132, Strengthen the test
around the second RemapACLToEffectiveModelIDs call by re-reading the affected
ACL records and asserting meta_model_id remains eff-id and meta_field_id remains
new-field. Extend the test fixtures to seed a Service under shell-id and its
matching effective Service under eff-id, assign ma1’s meta_service_id to the
shell service, and assert the remap updates it to the effective service ID,
thereby exercising remapOrphanServices.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@modules/auth/service/models/_resolve_effective_model.ts`:
- Around line 36-47: Ensure the effective-model lookup always includes ModuleId
in the fields passed to MetaModel.Search, even when the caller-provided fields
array omits it. Update the surrounding resolver logic for the effective-row
selection, preserving the caller’s requested fields while guaranteeing ModuleId
is available to moduleIdEmpty().

In `@pkg/meta/acl_remap.go`:
- Around line 169-198: The ACL remap helpers currently suppress all GORM Take
errors; import errors and in pkg/meta/acl_remap.go lines 169-198 update the
service lookups at lines 170, 188, and 196 to continue only for errors.Is(err,
gorm.ErrRecordNotFound), returning other errors wrapped with the service ID.
Apply the same handling in lines 121-134 at lookups 123 and 132, wrapping
non-not-found errors with the field-rule ID; no other sites require changes.

---

Nitpick comments:
In `@pkg/meta/acl_remap_test.go`:
- Around line 126-132: Strengthen the test around the second
RemapACLToEffectiveModelIDs call by re-reading the affected ACL records and
asserting meta_model_id remains eff-id and meta_field_id remains new-field.
Extend the test fixtures to seed a Service under shell-id and its matching
effective Service under eff-id, assign ma1’s meta_service_id to the shell
service, and assert the remap updates it to the effective service ID, thereby
exercising remapOrphanServices.

In `@pkg/meta/acl_remap.go`:
- Line 98: Remove the unused oldToEffective parameter from
remapFieldRuleFieldIDs and update its call site accordingly. Delete the loop
statement that discards oldToEffective, while preserving the function’s existing
remapping behavior.
- Around line 73-95: Wrap the entire mutation phase in pkg/meta/acl_remap.go’s
visible remap flow, including the table updates, remapFieldRuleFieldIDs, and
remapOrphanServices, in a single db.Transaction callback. Return each error from
the callback so any failure rolls back all ACL changes, and only return the
transaction result after it commits successfully.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5cd7c8d5-7d48-4008-91bc-f1c79ec8d93f

📥 Commits

Reviewing files that changed from the base of the PR and between a4dcddd and b2c2947.

📒 Files selected for processing (35)
  • internal/bootstrap/service/coordinator.go
  • internal/module/artifact/build/web/webBuilder.go
  • internal/module/artifact/generate/generator.go
  • internal/module/artifact/generate/generator_test.go
  • internal/module/evolution/data/loader.go
  • internal/module/evolution/data/translated_seed.go
  • modules/auth/service/models/_resolve_effective_model.ts
  • modules/auth/service/models/_user_field_rule_eval.ts
  • modules/auth/service/models/_user_method_access.ts
  • modules/auth/service/models/_user_permission_state_acl.ts
  • modules/auth/service/models/_user_record_rule_eval.ts
  • modules/auth/service/tests/authz_context_memoization.test.ts
  • modules/auth/service/tests/authz_mutation_crud_coverage.test.ts
  • modules/auth/service/tests/bootstrap_gift_pack.test.ts
  • modules/auth/service/tests/check_method_access_company_scope.test.ts
  • modules/auth/service/tests/check_method_access_diagnostics.test.ts
  • modules/auth/service/tests/field_rule.test.ts
  • modules/auth/service/tests/permission_state.test.ts
  • modules/auth/service/tests/record_rule.test.ts
  • modules/auth/service/tests/record_rule_eval_edges.test.ts
  • modules/auth/service/tests/role_ui_resource_sync.test.ts
  • modules/document/service/tests/_owner_auth_test_fixtures.ts
  • modules/meta/service/models/argument_raw.ts
  • modules/meta/service/models/decorator_raw.ts
  • modules/meta/service/models/field_raw.ts
  • modules/meta/service/models/index.ts
  • modules/meta/service/models/model_raw.ts
  • modules/meta/service/models/parameter_raw.ts
  • modules/meta/service/models/service_raw.ts
  • modules/meta/service/models/type_parameter_raw.ts
  • pkg/meta/acl_remap.go
  • pkg/meta/acl_remap_test.go
  • pkg/meta/dual_store_migrate.go
  • pkg/meta/lookup_effective.go
  • pkg/meta/lookup_effective_test.go

Comment thread modules/auth/service/models/_resolve_effective_model.ts Outdated
Comment thread pkg/meta/acl_remap.go
Comment thread pkg/meta/acl_remap.go Outdated
Comment thread modules/auth/service/models/_resolve_effective_model.ts Outdated
- Always fetch ModuleId/UpdatedAt in the Auth effective resolver and mirror Go Id/UpdatedAt tie-breaks when shells coexist.

- Remap field ACL FKs even when model ids are already effective; treat only ErrRecordNotFound as skip; wrap ACL rewrites in one transaction.

Co-authored-by: Cursor <cursoragent@cursor.com>
@buke

buke commented Aug 5, 2026

Copy link
Copy Markdown
Contributor Author

@cursor review

@cursor cursor Bot 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.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit f5eb589. Configure here.

buke and others added 2 commits August 5, 2026 17:43
- Add ACL remap hooks and branch/error coverage for remap, migrate, and lookup.

- Cover Auth effective resolve, field-rule empty appId, ACL dedupe, and bootstrap admin lookup paths.

Co-authored-by: Cursor <cursoragent@cursor.com>
- Split compound branches that Codecov marked partial and drop dead optional chaining.

- Extend resolve/ACL unit tests for ModuleId/UpdatedAt edge cases and null Search rows.

Co-authored-by: Cursor <cursoragent@cursor.com>

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

🧹 Nitpick comments (9)
pkg/meta/acl_remap_coverage_test.go (5)

92-116: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

This subtest verifies no error, not the documented behavior.

The name is skip_invalid_live_and_deleted_rows, and the fixtures set up a soft-deleted shell for the same (auth, User) key as eff, plus a duplicate live eff2. The only assertion is that RemapACLToEffectiveModelIDs returns nil. The test passes if the function skips every row, and it passes if the function picks the wrong effective model between eff and eff2.

seedACLTables created the ACL tables, but no ACL rows were inserted, so nothing observable is produced. Insert a rule that points at shell and assert its meta_model_id afterwards. pickEffectiveAmong must choose eff over eff2 here, because eff has an empty ModuleId; asserting the resulting id locks that tie-break in.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/meta/acl_remap_coverage_test.go` around lines 92 - 116, Strengthen the
skip_invalid_live_and_deleted_rows subtest by inserting an ACL rule referencing
shell, then assert after RemapACLToEffectiveModelIDs that its meta_model_id
points to eff. Keep the invalid-id fixture and duplicate live models, ensuring
the assertion verifies pickEffectiveAmong selects eff over eff2 because eff has
an empty ModuleId.

283-299: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Assert the rollback that this subtest is positioned to prove.

exec_field_id_error lets the meta_model_id UPDATEs succeed through prev(db, sql, values...) and then fails the meta_field_id UPDATE. That is the exact shape needed to prove the transaction added in RemapACLToEffectiveModelIDs reverts partial work.

The subtest only checks the error string. Read one of the model-id columns after the call and assert it holds the pre-call value. Without that assertion, a regression that drops db.Transaction and calls the helpers on db still passes every test in this file.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/meta/acl_remap_coverage_test.go` around lines 283 - 299, Extend the
exec_field_id_error subtest after RemapACLToEffectiveModelIDs returns to query a
model-id column affected by the earlier successful update, such as
meta_model_id, and assert it still has its pre-call value. Keep the existing
error assertion and use the test’s established database helpers, ensuring the
check proves the transaction rolled back partial updates.

183-194: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove the debugging note and seed fr-no-repl directly.

The trailing comment on line 187 records a train of thought rather than intent: "of under shell; no Login on wrong model? Wait of name Login exists on eff as nf ... Use field only on shell with unique name." A future reader cannot tell what the line asserts.

Lines 187, 189-193 also insert fr-no-repl with of, create the lonely field, then UPDATE the row to lonely. Create lonely before the insert and seed the final value once.

♻️ Proposed cleanup
 		mustExecACL(`INSERT INTO auth_role_field_rule (id, meta_model_id, meta_field_id) VALUES (?,?,?)`, "fr-blank-name", "eff-h", "bnf")
-		mustExecACL(`INSERT INTO auth_role_field_rule (id, meta_model_id, meta_field_id) VALUES (?,?,?)`, "fr-no-repl", "eff-h", "of") // of under shell; no Login on wrong model? Wait of name Login exists on eff as nf - Take by model+name finds nf. Use field only on shell with unique name.
-		// Replace fr-no-repl: field with name only on shell.
+		// "Lonely" exists only under the shell model, so no replacement field
+		// resolves under the effective model and the rule is skipped.
 		lonely := &Field{BaseModel: BaseModel{Id: sql.NullString{String: "lonely", Valid: true}}, Name: "Lonely", ModelId: shell.Id}
 		if err := db.Create(lonely).Error; err != nil {
 			t.Fatalf("lonely: %v", err)
 		}
-		mustExecACL(`UPDATE auth_role_field_rule SET meta_field_id=? WHERE id=?`, "lonely", "fr-no-repl")
+		mustExecACL(`INSERT INTO auth_role_field_rule (id, meta_model_id, meta_field_id) VALUES (?,?,?)`, "fr-no-repl", "eff-h", "lonely")
 		mustExecACL(`INSERT INTO auth_role_field_rule (id, meta_model_id, meta_field_id) VALUES (?,?,?)`, "fr-same", "eff-h", "nf")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/meta/acl_remap_coverage_test.go` around lines 183 - 194, Remove the
trailing debugging comment from the fr-no-repl seed in the ACL coverage test. In
the surrounding setup, create the lonely Field before inserting fr-no-repl, then
insert that rule once with lonely as meta_field_id and remove the subsequent
UPDATE, preserving the existing fr-same setup.

424-431: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Check the errors from these fixture writes.

Lines 424, 425, 430, 431, 446, and 449 discard the result of db.Create and db.Exec. If a fixture write fails, the subtest still reports success, because the only assertion is that RemapACLToEffectiveModelIDs returns nil, and it returns nil when there is no data.

Every other subtest in this file fails fast with t.Fatalf. Use the same pattern here, or add a small mustCreate(t, db, v) helper and use it across the file.

Also applies to: 446-449

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/meta/acl_remap_coverage_test.go` around lines 424 - 431, Check and fail
fast on every fixture write in the affected subtest: replace ignored results
from db.Create and db.Exec, including the writes around shell, eff, svc, and
auth_role_method_access, with the file’s existing t.Fatalf pattern or a shared
mustCreate(t, db, v) helper. Apply the same handling to the additional writes at
the referenced later locations so fixture setup errors cannot be masked.

372-409: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

invalid_eff_id_in_map does not reach the branch it names, and it contains a dead assignment.

Line 379 assigns aclLoadLiveModels. Line 394 reassigns it before any call to RemapACLToEffectiveModelIDs. The first stub is dead.

The surviving stubs are also mismatched. aclLoadLiveModels (line 394) returns the keys auth/Z and auth/BadEff. aclLoadAllModels (line 385) returns rows for auth/User and auth/MissingEff. No key is present in both, so oldToEffective stays empty and the function performs no rewrite. The only assertion is that the error is nil, which a no-op satisfies.

The comments at lines 389, 393, 398, and 405 confirm this. Line 405 states "Replace BadEff's entry: can't easily."

The named branch is !eff.Id.Valid at pkg/meta/acl_remap.go line 112. Reaching it needs effectiveByKey to hold an entry with an invalid Id, which the builder at line 82 prevents. The branch is therefore unreachable through the public function.

Two options. Delete the subtest and remove the now-unreachable !eff.Id.Valid guard in acl_remap.go line 112. Or keep the guard as defensive code and replace this subtest with a comment that records why it is not covered. Either way, remove the abandoned attempts and the dead assignment.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/meta/acl_remap_coverage_test.go` around lines 372 - 409, The
invalid_eff_id_in_map subtest is dead code and cannot reach the !eff.Id.Valid
branch because effectiveByKey only stores models with valid IDs. Remove the
abandoned stubs, conflicting reassignment, and ineffective assertions; either
delete the subtest and the unreachable guard in RemapACLToEffectiveModelIDs, or
retain the guard while replacing the test with a concise comment documenting
that the branch is unreachable through the public function.
pkg/meta/acl_remap.go (3)

170-191: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Unresolvable ACL references are skipped with no signal to the operator. Both remap helpers use continue for every reference they cannot resolve. The row keeps its stale foreign key, the transaction commits, and MigrateIMDCatalogToDualStore and RecomputeAllEffectiveFromRaw report success. A stale meta_field_id or meta_service_id is an ACL rule that no longer matches, so permissions change silently and no output shows it happened.

  • pkg/meta/acl_remap.go#L170-L191: count the three skip reasons in remapFieldRuleFieldIDs — old field row missing (line 174), old field name blank (line 180), no replacement field under (modelID, name) (line 185). Return or log the totals with the rule IDs.
  • pkg/meta/acl_remap.go#L254-L266: count the skip reasons in remapOrphanServices the same way — effective model not found (line 250), effective id invalid (line 255), no replacement service under (eff.Id, name) (line 260), replacement id invalid or unchanged (line 265). Report the totals with the method-access IDs.

Aggregate both counts into one summary that the migration emits. The skip behavior itself is the right default; the missing part is the record of it.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/meta/acl_remap.go` around lines 170 - 191, Add structured counters and
rule/access IDs to the skip paths in remapFieldRuleFieldIDs (missing old field,
blank name, missing replacement) and remapOrphanServices (missing model, invalid
IDs, missing or unchanged replacement). Preserve the continue behavior,
aggregate both helpers’ counts into one summary, and have
MigrateIMDCatalogToDualStore and RecomputeAllEffectiveFromRaw emit that summary.

127-139: 🚀 Performance & Scalability | 🔵 Trivial | ⚖️ Poor tradeoff

The model remap issues one UPDATE per table per mapping.

oldToEffective holds one entry for every historical shell that resolves to a different effective model. The loop runs 3 × len(oldToEffective) UPDATE statements inside a single transaction. On a large catalog after a full recompute, that map can hold one entry per replaced model per module generation.

A single statement per table removes the round-trip cost:

♻️ Batch the rewrite with a temporary mapping table
+		if len(oldToEffective) > 0 {
+			if err := aclExec(tx, `CREATE TEMP TABLE acl_model_remap (old_id TEXT PRIMARY KEY, new_id TEXT)`); err != nil {
+				return fmt.Errorf("create remap temp table: %w", err)
+			}
+			for oldID, newID := range oldToEffective {
+				if err := aclExec(tx, `INSERT INTO acl_model_remap (old_id, new_id) VALUES (?, ?)`, oldID, newID); err != nil {
+					return fmt.Errorf("seed remap temp table: %w", err)
+				}
+			}
+		}

Then each table needs one statement:

UPDATE <table>
SET meta_model_id = (SELECT new_id FROM acl_model_remap WHERE old_id = meta_model_id)
WHERE meta_model_id IN (SELECT old_id FROM acl_model_remap)

The current form is correct. Apply this only if catalog size makes the migration slow.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/meta/acl_remap.go` around lines 127 - 139, Only optimize the remap path
if migration performance requires it: in the transaction surrounding the table
loop, create and populate a temporary acl_model_remap table from oldToEffective,
then update each table once using that mapping table to replace matching
meta_model_id values. Preserve aclHasTable checks, transaction/error handling,
and the existing behavior when no mappings exist.

14-63: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider moving the injection seam out of package-level mutable globals.

The hooks ship in the production binary as package-level variables. Any test that reassigns them mutates shared state for the whole package. The current tests restore each hook with t.Cleanup, so the behavior is correct today, but the pattern blocks t.Parallel() in pkg/meta tests and it lets a missed Cleanup leak a stub into unrelated tests.

A struct of function fields with a package default, or an unexported interface passed into the remap functions, gives the same error-path coverage with no shared mutable state.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/meta/acl_remap.go` around lines 14 - 63, Replace the package-level
mutable hook variables in the ACL remap injection seam with per-invocation
dependencies: define a hook struct or unexported interface containing the
existing operations, provide production defaults, and pass it through the
relevant remap functions. Update tests to construct overrides rather than
reassign shared globals, preserving existing error-path coverage and enabling
parallel execution.
pkg/meta/lookup_effective_test.go (1)

85-130: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add an order-independence case for pickEffectiveAmong.

The four cases cover each precedence level: single row, UpdatedAt, Id, and empty ModuleId outranking UpdatedAt. Each passes one fixed slice order.

RemapACLToEffectiveModelIDs depends on more than the precedence order. At pkg/meta/acl_remap.go line 86 it folds pairwise over map iteration:

picked := pickEffectiveAmong([]Model{existing, row})

Map iteration order is random in Go. The fold produces the same result as LookupEffectiveModel, which passes all rows at once, only if the comparison is a total order. Assert that directly by running each existing case with the slice reversed and expecting the same id, and by adding one three-element case compared against both a forward fold and a reverse fold.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/meta/lookup_effective_test.go` around lines 85 - 130, Extend the
“single_row_and_tie_breaks” tests for order independence by rerunning each
existing two-row precedence case with its slice reversed and asserting the same
selected ID. Add a three-element case and verify that pickEffectiveAmong returns
the same ID as both forward and reverse pairwise folds, matching the all-at-once
result and confirming total-order behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@modules/auth/service/models/_resolve_effective_model.ts`:
- Around line 92-94: Remove the fixed limit from the candidate query used before
pickEffectiveAmong, and fetch all matching declaration shells through the
existing pagination mechanism instead. Ensure older effective rows with empty
ModuleId values remain eligible, and add a regression case covering more than 50
shells with one older effective row.

In `@pkg/meta/acl_remap.go`:
- Around line 236-253: Before calling aclLookupEffective in the service remap
loop, skip the historical model when hist.Application or hist.Name is blank,
matching the existing blank-key handling in the main loop. Update the logic
after aclTakeModelUnscoped and before aclLookupEffective so invalid historical
lookup keys continue without aborting the remap; preserve existing error
handling for valid keys.

---

Nitpick comments:
In `@pkg/meta/acl_remap_coverage_test.go`:
- Around line 92-116: Strengthen the skip_invalid_live_and_deleted_rows subtest
by inserting an ACL rule referencing shell, then assert after
RemapACLToEffectiveModelIDs that its meta_model_id points to eff. Keep the
invalid-id fixture and duplicate live models, ensuring the assertion verifies
pickEffectiveAmong selects eff over eff2 because eff has an empty ModuleId.
- Around line 283-299: Extend the exec_field_id_error subtest after
RemapACLToEffectiveModelIDs returns to query a model-id column affected by the
earlier successful update, such as meta_model_id, and assert it still has its
pre-call value. Keep the existing error assertion and use the test’s established
database helpers, ensuring the check proves the transaction rolled back partial
updates.
- Around line 183-194: Remove the trailing debugging comment from the fr-no-repl
seed in the ACL coverage test. In the surrounding setup, create the lonely Field
before inserting fr-no-repl, then insert that rule once with lonely as
meta_field_id and remove the subsequent UPDATE, preserving the existing fr-same
setup.
- Around line 424-431: Check and fail fast on every fixture write in the
affected subtest: replace ignored results from db.Create and db.Exec, including
the writes around shell, eff, svc, and auth_role_method_access, with the file’s
existing t.Fatalf pattern or a shared mustCreate(t, db, v) helper. Apply the
same handling to the additional writes at the referenced later locations so
fixture setup errors cannot be masked.
- Around line 372-409: The invalid_eff_id_in_map subtest is dead code and cannot
reach the !eff.Id.Valid branch because effectiveByKey only stores models with
valid IDs. Remove the abandoned stubs, conflicting reassignment, and ineffective
assertions; either delete the subtest and the unreachable guard in
RemapACLToEffectiveModelIDs, or retain the guard while replacing the test with a
concise comment documenting that the branch is unreachable through the public
function.

In `@pkg/meta/acl_remap.go`:
- Around line 170-191: Add structured counters and rule/access IDs to the skip
paths in remapFieldRuleFieldIDs (missing old field, blank name, missing
replacement) and remapOrphanServices (missing model, invalid IDs, missing or
unchanged replacement). Preserve the continue behavior, aggregate both helpers’
counts into one summary, and have MigrateIMDCatalogToDualStore and
RecomputeAllEffectiveFromRaw emit that summary.
- Around line 127-139: Only optimize the remap path if migration performance
requires it: in the transaction surrounding the table loop, create and populate
a temporary acl_model_remap table from oldToEffective, then update each table
once using that mapping table to replace matching meta_model_id values. Preserve
aclHasTable checks, transaction/error handling, and the existing behavior when
no mappings exist.
- Around line 14-63: Replace the package-level mutable hook variables in the ACL
remap injection seam with per-invocation dependencies: define a hook struct or
unexported interface containing the existing operations, provide production
defaults, and pass it through the relevant remap functions. Update tests to
construct overrides rather than reassign shared globals, preserving existing
error-path coverage and enabling parallel execution.

In `@pkg/meta/lookup_effective_test.go`:
- Around line 85-130: Extend the “single_row_and_tie_breaks” tests for order
independence by rerunning each existing two-row precedence case with its slice
reversed and asserting the same selected ID. Add a three-element case and verify
that pickEffectiveAmong returns the same ID as both forward and reverse pairwise
folds, matching the all-at-once result and confirming total-order behavior.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8e45ff8b-7411-453b-845d-a88654889cb2

📥 Commits

Reviewing files that changed from the base of the PR and between b2c2947 and 8a98608.

📒 Files selected for processing (11)
  • internal/bootstrap/service/coordinator_admin_coverage_test.go
  • modules/auth/service/models/_resolve_effective_model.ts
  • modules/auth/service/models/_user_permission_state_acl.ts
  • modules/auth/service/tests/field_rule_effective_resolve.test.ts
  • modules/auth/service/tests/permission_state_acl_source.test.ts
  • modules/auth/service/tests/resolve_effective_model.test.ts
  • pkg/meta/acl_remap.go
  • pkg/meta/acl_remap_coverage_test.go
  • pkg/meta/acl_remap_test.go
  • pkg/meta/dual_store_migrate.go
  • pkg/meta/lookup_effective_test.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • pkg/meta/dual_store_migrate.go
  • modules/auth/service/models/_user_permission_state_acl.ts

Comment thread modules/auth/service/models/_resolve_effective_model.ts Outdated
Comment thread pkg/meta/acl_remap.go
buke and others added 2 commits August 5, 2026 18:52
- Rewrite rowUpdatedAt null/updated_at fallthrough so the null-ts path is exercised.

- Normalize ACL label trimming via an explicit null check and cover null Application/Name rows.

Co-authored-by: Cursor <cursoragent@cursor.com>
- Skip blank historical model keys in ACL service remap and paginate Auth effective lookups.

- Strengthen remap/lookup tests for tie-break, rollback, and fixture error checking.

Co-authored-by: Cursor <cursoragent@cursor.com>
@buke
buke merged commit 3dc619b into main Aug 5, 2026
43 checks passed
@buke
buke deleted the feat/meta-effective-dual-store-eds3 branch August 5, 2026 12:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant