mirror of
https://github.com/microsoft/BCQuality.git
synced 2026-10-05 22:56:55 +01:00
Custom-laget bestaar nu begge CI-checks: 72 validator-fejl -> 0
Normalisering af alle 39 custom knowledge-filer til READ-kontraktens skema (validate_frontmatter.py + Test-KnowledgeIndex.ps1 begge groenne): - R01/R02: 28 filer manglede frontmatter eller brugte aeldre skemaer (title/category/severity/rule-id m.fl.) - alle har nu praecis de 6 kraevede noegler; keywords haandskrevet pr. fil da de driver worklist-selektionen i INDEX/knowledge-index - R09: manglende Description-sektion - regel-agtige foersteoverskrifter (Core Rule/Rule/Regel/Core Principle) omdoebt, eller sektion indsat efter titlen hvor intro-tekst fandtes - R10: fenced code blocks konverteret til 4-space indrykkede blokke i alle filer (indhold uaendret) - R11: 4 filer over 100 linjer fortaettet redaktionelt uden semantisk tab (ai-eval-scores 143->100, git-lifecycle 121->97, permission-sets 113->99, test-feature-scenario-tags 105->91) - R05: AL0197->al0197, add_repo->add-repo; keyword-lister trimmet til maks 10 Ingen regler er fjernet eller aendret i betydning - kun form. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
ec2892f0ab
commit
dd5637b1db
39 changed files with 729 additions and 814 deletions
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
bc-version: [all]
|
||||
domain: architecture
|
||||
keywords: [build, output, alpackages, duplicate, language-server, app-package, project-root, AL0197]
|
||||
keywords: [build, output, alpackages, duplicate, language-server, app-package, project-root, al0197]
|
||||
technologies: [al]
|
||||
countries: [w1]
|
||||
application-area: [all]
|
||||
|
|
@ -20,16 +20,12 @@ AL build output (`.app` files) **must not** accumulate in the project root folde
|
|||
Configure the build output path to a dedicated subfolder that is excluded from language server scanning.
|
||||
|
||||
In `.vscode/settings.json`:
|
||||
```json
|
||||
{
|
||||
"al.outputPath": ".output"
|
||||
}
|
||||
```
|
||||
{
|
||||
"al.outputPath": ".output"
|
||||
}
|
||||
|
||||
When using the MCP `al_build` tool, pass `outputPath` explicitly:
|
||||
```
|
||||
al_build projectPath="..." outputPath=".output/AppName.app"
|
||||
```
|
||||
al_build projectPath="..." outputPath=".output/AppName.app"
|
||||
|
||||
Add `.output/` to `.gitignore` if not already excluded.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,14 @@
|
|||
---
|
||||
bc-version: [all]
|
||||
domain: architecture
|
||||
keywords: [identifiers, naming, english, captions, translation]
|
||||
technologies: [al]
|
||||
countries: [w1]
|
||||
application-area: [all]
|
||||
---
|
||||
# AL Naming Convention: English Identifiers Only
|
||||
|
||||
## Core Rule
|
||||
## Description
|
||||
|
||||
All AL identifiers must be written in English, regardless of the developer's native language. "Translations are handled separately via XLIFF files — never by writing Danish, German or other language identifiers in AL source code."
|
||||
|
||||
|
|
|
|||
|
|
@ -39,15 +39,13 @@ Ask before coding if any of the following is true:
|
|||
|
||||
State what you understand the task to be, then list the specific questions:
|
||||
|
||||
```
|
||||
I understand the task as: [one sentence summary]
|
||||
I understand the task as: [one sentence summary]
|
||||
|
||||
Before I proceed, I need clarification on:
|
||||
1. [specific question]
|
||||
2. [specific question]
|
||||
Before I proceed, I need clarification on:
|
||||
1. [specific question]
|
||||
2. [specific question]
|
||||
|
||||
I will not write any code until these are answered.
|
||||
```
|
||||
I will not write any code until these are answered.
|
||||
|
||||
Do not write partial code while waiting. Do not write "placeholder" code.
|
||||
Do not write code with TODO comments where a business decision is needed.
|
||||
|
|
@ -66,29 +64,25 @@ files first and resolve the ambiguity yourself before asking the developer.
|
|||
|
||||
## Anti Pattern
|
||||
|
||||
```
|
||||
// WRONG: Assuming and building
|
||||
// Task: "write a test for the vendor flow"
|
||||
// Agent assumes: Vendor, Incoming, Handle+Invoice, no contact
|
||||
// Writes 80 lines of code
|
||||
// Developer says: "I meant outgoing flow with a customer"
|
||||
// Result: wasted work, possible production code changes to revert
|
||||
```
|
||||
// WRONG: Assuming and building
|
||||
// Task: "write a test for the vendor flow"
|
||||
// Agent assumes: Vendor, Incoming, Handle+Invoice, no contact
|
||||
// Writes 80 lines of code
|
||||
// Developer says: "I meant outgoing flow with a customer"
|
||||
// Result: wasted work, possible production code changes to revert
|
||||
|
||||
## Best Practice
|
||||
|
||||
```
|
||||
// CORRECT: Clarify first
|
||||
// Task: "write a test for the vendor flow"
|
||||
// CORRECT: Clarify first
|
||||
// Task: "write a test for the vendor flow"
|
||||
|
||||
I understand the task as: writing a test codeunit for a Settlement Voucher
|
||||
flow where the counterparty is a Vendor.
|
||||
I understand the task as: writing a test codeunit for a Settlement Voucher
|
||||
flow where the counterparty is a Vendor.
|
||||
|
||||
Before I proceed, I need clarification on:
|
||||
1. Incoming (vendor delivers goods) or Outgoing (vendor picks up goods)?
|
||||
2. Handle-only, Invoice-only, or combined Handle+Invoice in one run?
|
||||
3. Should the test use an existing vendor from the database or create one
|
||||
via LibraryPurchase.CreateVendor?
|
||||
Before I proceed, I need clarification on:
|
||||
1. Incoming (vendor delivers goods) or Outgoing (vendor picks up goods)?
|
||||
2. Handle-only, Invoice-only, or combined Handle+Invoice in one run?
|
||||
3. Should the test use an existing vendor from the database or create one
|
||||
via LibraryPurchase.CreateVendor?
|
||||
|
||||
I will not write any code until these are answered.
|
||||
```
|
||||
I will not write any code until these are answered.
|
||||
|
|
|
|||
|
|
@ -1,3 +1,11 @@
|
|||
---
|
||||
bc-version: [all]
|
||||
domain: architecture
|
||||
keywords: [claude-md, agents, routing, visibility, setup]
|
||||
technologies: [al]
|
||||
countries: [w1]
|
||||
application-area: [all]
|
||||
---
|
||||
bc-version: [all]
|
||||
domain: architecture
|
||||
keywords: [claude-md, agents, visibility, setup, mode-b, curabis-standard]
|
||||
|
|
@ -35,9 +43,7 @@ with a proposed addition before the session continues.
|
|||
|
||||
After running Mode B (or any agent install), compare:
|
||||
|
||||
```
|
||||
Get-ChildItem .github/.agents/*.agent.md | Select-Object -ExpandProperty BaseName
|
||||
```
|
||||
Get-ChildItem .github/.agents/*.agent.md | Select-Object -ExpandProperty BaseName
|
||||
|
||||
against the agent references in CLAUDE.md. Any filename present in the directory
|
||||
but absent from CLAUDE.md is a gap that must be surfaced.
|
||||
|
|
@ -46,13 +52,11 @@ but absent from CLAUDE.md is a gap that must be surfaced.
|
|||
|
||||
When a gap is found, output exactly this before continuing:
|
||||
|
||||
```
|
||||
⚠️ Ny agent installeret men ikke refereret i CLAUDE.md:
|
||||
⚠️ Ny agent installeret men ikke refereret i CLAUDE.md:
|
||||
|
||||
- <agent-navn>.agent.md
|
||||
- <agent-navn>.agent.md
|
||||
|
||||
Claude kan ikke kalde denne agent medmindre den tilføjes til CLAUDE.md.
|
||||
Vil du have mig til at tilføje den nu?
|
||||
```
|
||||
Claude kan ikke kalde denne agent medmindre den tilføjes til CLAUDE.md.
|
||||
Vil du have mig til at tilføje den nu?
|
||||
|
||||
Do not continue with other activity until the developer has responded.
|
||||
|
|
|
|||
|
|
@ -1,3 +1,11 @@
|
|||
---
|
||||
bc-version: [all]
|
||||
domain: architecture
|
||||
keywords: [commit-message, bc-task, task-id, traceability, git]
|
||||
technologies: [al]
|
||||
countries: [w1]
|
||||
application-area: [all]
|
||||
---
|
||||
---
|
||||
name: commit-message-must-include-bc-task-id
|
||||
description: >
|
||||
|
|
@ -21,19 +29,15 @@ used across Curabis teams.
|
|||
|
||||
## Anti Pattern
|
||||
|
||||
```
|
||||
Add Price Lookup feature — FindPrice page, tier prices, currency conversion
|
||||
```
|
||||
Add Price Lookup feature — FindPrice page, tier prices, currency conversion
|
||||
|
||||
No traceability. Impossible to find the BC task from git history.
|
||||
|
||||
## Best Practice
|
||||
|
||||
```
|
||||
[#8738] Add Price Lookup feature — FindPrice page, tier prices, currency conversion
|
||||
[#8738] Add 22 UI tests for PRICING LOOKUP feature
|
||||
[#8738] Add translations, shared project memory and cspell config
|
||||
```
|
||||
[#8738] Add Price Lookup feature — FindPrice page, tier prices, currency conversion
|
||||
[#8738] Add 22 UI tests for PRICING LOOKUP feature
|
||||
[#8738] Add translations, shared project memory and cspell config
|
||||
|
||||
## The two task numbers — use taskId, not taskNo
|
||||
|
||||
|
|
@ -65,4 +69,4 @@ create-task workflow) or ask the project manager to register the work.
|
|||
## Scope
|
||||
|
||||
All commits that reach the main branch — feature, fix, test, chore, docs.
|
||||
Merge commits and auto-generated commits (renovate, al-go) are exempt.
|
||||
Merge commits and auto-generated commits (renovate, al-go) are exempt.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
bc-version: [all]
|
||||
domain: architecture
|
||||
keywords: [dependency, source, add_repo, github, curabis, closed-source, test, symbol, black-box]
|
||||
keywords: [dependency, source, add-repo, github, curabis, closed-source, test, symbol, black-box]
|
||||
technologies: [al]
|
||||
countries: [w1]
|
||||
application-area: [all]
|
||||
|
|
@ -49,26 +49,22 @@ the current project.
|
|||
|
||||
## Anti Pattern
|
||||
|
||||
```
|
||||
// WRONG: reverse-engineering the compiled symbol package instead of reading source
|
||||
// Agent parses SymbolReference.json from .alpackages/*.app to learn
|
||||
// Contract Management table fields and public procedure signatures.
|
||||
// Result: incomplete picture, missed validation logic, excluded feature from tests.
|
||||
```
|
||||
// WRONG: reverse-engineering the compiled symbol package instead of reading source
|
||||
// Agent parses SymbolReference.json from .alpackages/*.app to learn
|
||||
// Contract Management table fields and public procedure signatures.
|
||||
// Result: incomplete picture, missed validation logic, excluded feature from tests.
|
||||
|
||||
## Best Practice
|
||||
|
||||
```
|
||||
// CORRECT: add the source repo and read it directly
|
||||
add_repo Curabis/ContractMgmt365app
|
||||
// CORRECT: add the source repo and read it directly
|
||||
add_repo Curabis/ContractMgmt365app
|
||||
|
||||
// Then read the actual table definitions, codeunits, and any Test Library
|
||||
// codeunits that may already exist in the repo's own test app.
|
||||
// Then read the actual table definitions, codeunits, and any Test Library
|
||||
// codeunits that may already exist in the repo's own test app.
|
||||
|
||||
// If no Test Library exists in the dependency's test app:
|
||||
// build GIVEN helpers in the consuming project's own Test Library codeunit
|
||||
// based on the REAL table field definitions and trigger logic you can now read.
|
||||
```
|
||||
// If no Test Library exists in the dependency's test app:
|
||||
// build GIVEN helpers in the consuming project's own Test Library codeunit
|
||||
// based on the REAL table field definitions and trigger logic you can now read.
|
||||
|
||||
## When to apply this rule
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,15 @@
|
|||
---
|
||||
bc-version: [all]
|
||||
domain: architecture
|
||||
keywords: [permission-set, api-page, web-service, exposure, security]
|
||||
technologies: [al]
|
||||
countries: [w1]
|
||||
application-area: [all]
|
||||
---
|
||||
# Exposed objects must be in at least one permission set
|
||||
|
||||
## Description
|
||||
|
||||
**Rule (CURABIS-ARCH-011):** Every *exposed* object in a CURABIS app must be a member of
|
||||
at least one permission set shipped by that app. "Exposed" means any object reachable from
|
||||
outside the app's own UI:
|
||||
|
|
|
|||
|
|
@ -1,13 +1,15 @@
|
|||
---
|
||||
name: feature-branch-must-merge-to-track-branch
|
||||
title: Feature branches must merge into the project's declared track branch
|
||||
category: architecture
|
||||
severity: required
|
||||
bc-version: [all]
|
||||
domain: architecture
|
||||
keywords: [git, feature-branch, track-branch, merge, workflow]
|
||||
technologies: [al]
|
||||
countries: [w1]
|
||||
application-area: [all]
|
||||
---
|
||||
|
||||
# Feature branches must merge into the project's declared track branch
|
||||
|
||||
## Rule
|
||||
## Description
|
||||
|
||||
When a project declares a track branch in `CLAUDE.md`, all feature branches
|
||||
MUST merge into that track branch — not into `main` directly. `main` is
|
||||
|
|
@ -17,10 +19,8 @@ reserved for releases and hotfixes.
|
|||
|
||||
The track branch is declared once in `CLAUDE.md`:
|
||||
|
||||
```yaml
|
||||
# Declares the integration target for this development sprint/module
|
||||
trackBranch: purchase
|
||||
```
|
||||
# Declares the integration target for this development sprint/module
|
||||
trackBranch: purchase
|
||||
|
||||
If no `trackBranch` is declared, `main` is the default and feature branches
|
||||
merge there directly.
|
||||
|
|
@ -46,33 +46,27 @@ The rule protects the invariant: **`main` is deployable at any moment.**
|
|||
|
||||
## The branching model
|
||||
|
||||
```
|
||||
main
|
||||
└── <track-branch> (e.g. "purchase" — lives for one sprint/module)
|
||||
└── feature/<name> ← development happens here
|
||||
└── feature/<name>
|
||||
└── bugfix/<name>
|
||||
└── hotfix/<name> ← branches from main, merges back to main
|
||||
```
|
||||
main
|
||||
└── <track-branch> (e.g. "purchase" — lives for one sprint/module)
|
||||
└── feature/<name> ← development happens here
|
||||
└── feature/<name>
|
||||
└── bugfix/<name>
|
||||
└── hotfix/<name> ← branches from main, merges back to main
|
||||
|
||||
At release: track-branch → main (via PR, after full QA).
|
||||
|
||||
## Non-compliant
|
||||
|
||||
```bash
|
||||
# Merging a feature directly to main when a track branch is declared in CLAUDE.md
|
||||
git checkout main
|
||||
git merge feature/my-feature # violates rule
|
||||
```
|
||||
# Merging a feature directly to main when a track branch is declared in CLAUDE.md
|
||||
git checkout main
|
||||
git merge feature/my-feature # violates rule
|
||||
|
||||
## Compliant
|
||||
|
||||
```bash
|
||||
# Read track branch from CLAUDE.md → merge there
|
||||
git checkout purchase
|
||||
git merge --no-ff feature/my-feature
|
||||
# Then sync BC: gitHubDevStatus = "Done"
|
||||
```
|
||||
# Read track branch from CLAUDE.md → merge there
|
||||
git checkout purchase
|
||||
git merge --no-ff feature/my-feature
|
||||
# Then sync BC: gitHubDevStatus = "Done"
|
||||
|
||||
## Scope
|
||||
|
||||
|
|
|
|||
|
|
@ -48,9 +48,7 @@ whether Mode B executes for a given repository.
|
|||
|
||||
At session start, compare:
|
||||
|
||||
```
|
||||
Local per-repo marker: .github/.agents/.bcquality-version (if present)
|
||||
```
|
||||
Local per-repo marker: .github/.agents/.bcquality-version (if present)
|
||||
|
||||
against the current BCQuality main SHA. If they differ (or the local marker is
|
||||
missing), run Mode B reconciliation for this repository regardless of what the
|
||||
|
|
@ -60,10 +58,8 @@ global `~/.claude/.bcquality-version` file says.
|
|||
|
||||
When a per-repo reconciliation gap is found, output exactly this before continuing:
|
||||
|
||||
```
|
||||
⚠️ Dette repository er ikke reconciled mod seneste BCQuality-SHA, selvom den
|
||||
globale versions-fil allerede er opdateret (formentlig af et andet projekt).
|
||||
Kører Mode B-reconciliation for dette repo nu.
|
||||
```
|
||||
⚠️ Dette repository er ikke reconciled mod seneste BCQuality-SHA, selvom den
|
||||
globale versions-fil allerede er opdateret (formentlig af et andet projekt).
|
||||
Kører Mode B-reconciliation for dette repo nu.
|
||||
|
||||
Do not silently skip Mode B just because the global marker looks current.
|
||||
|
|
|
|||
|
|
@ -42,9 +42,7 @@ before the update is considered complete.
|
|||
After any Mode B run, compare the list of files in `curabis-standard.agent.md`'s
|
||||
Mode B template table against:
|
||||
|
||||
```
|
||||
Get-ChildItem .github/.agents/*.agent.md | Select-Object -ExpandProperty BaseName
|
||||
```
|
||||
Get-ChildItem .github/.agents/*.agent.md | Select-Object -ExpandProperty BaseName
|
||||
|
||||
Any template file present in the table but absent from the directory is a gap —
|
||||
install it, then surface it per `claude-md-must-reference-all-agents.md` if it
|
||||
|
|
@ -54,12 +52,10 @@ also needs a CLAUDE.md reference.
|
|||
|
||||
When a reconciliation gap is found, output exactly this before continuing:
|
||||
|
||||
```
|
||||
⚠️ Mode B kørte, men følgende template-fil(er) blev ikke installeret:
|
||||
⚠️ Mode B kørte, men følgende template-fil(er) blev ikke installeret:
|
||||
|
||||
- <agent-navn>.agent.md
|
||||
- <agent-navn>.agent.md
|
||||
|
||||
Vil du have mig til at installere den/dem nu?
|
||||
```
|
||||
Vil du have mig til at installere den/dem nu?
|
||||
|
||||
Do not continue with other activity until the developer has responded.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,14 @@
|
|||
---
|
||||
bc-version: [all]
|
||||
domain: architecture
|
||||
keywords: [namespace, verification, bcapps, source-of-truth]
|
||||
technologies: [al]
|
||||
countries: [w1]
|
||||
application-area: [all]
|
||||
---
|
||||
# AL Language Namespace Verification Rule
|
||||
|
||||
## Core Requirement
|
||||
## Description
|
||||
|
||||
When adding variables or references to Business Central objects, agents must **verify namespaces by reading the actual source file**—not by inference or training data assumptions.
|
||||
|
||||
|
|
|
|||
|
|
@ -70,12 +70,10 @@ stale symbol cache issue — not a missing implementation.
|
|||
|
||||
When this situation occurs, output exactly this message before stopping:
|
||||
|
||||
```
|
||||
WARNING: VS Code needs a refresh before I can check for real compilation errors.
|
||||
WARNING: VS Code needs a refresh before I can check for real compilation errors.
|
||||
|
||||
Please run: Ctrl+Shift+P -> AL: Reload Extension
|
||||
Please run: Ctrl+Shift+P -> AL: Reload Extension
|
||||
|
||||
Let me know when the refresh is done and I will re-check diagnostics.
|
||||
```
|
||||
Let me know when the refresh is done and I will re-check diagnostics.
|
||||
|
||||
Do not continue with any other activity until the developer confirms the refresh.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,14 @@
|
|||
---
|
||||
bc-version: [all]
|
||||
domain: architecture
|
||||
keywords: [pages, business-logic, codeunit, separation-of-concerns]
|
||||
technologies: [al]
|
||||
countries: [w1]
|
||||
application-area: [all]
|
||||
---
|
||||
# CURABIS Architecture: Page Presentation vs. Business Logic
|
||||
|
||||
## Core Rule
|
||||
## Description
|
||||
|
||||
In CURABIS codebases, pages serve exclusively as presentation layers. All business logic—including calculations, validations, and record modifications—must reside in codeunits, not in page triggers or actions. This standard is more rigorous than general Business Central guidance and applies uniformly across all CURABIS PTE applications.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,14 @@
|
|||
---
|
||||
bc-version: [all]
|
||||
domain: architecture
|
||||
keywords: [permission-set, least-privilege, tiers, security]
|
||||
technologies: [al]
|
||||
countries: [w1]
|
||||
application-area: [all]
|
||||
---
|
||||
# CURABIS Architecture: Permission Sets Must Follow Least-Privilege Hierarchy
|
||||
|
||||
## Core Rule
|
||||
## Description
|
||||
|
||||
Permission sets in CURABIS apps must be structured in access tiers following the least-privilege principle. Tiers must be **additive** — each tier includes the one below it via `IncludedPermissionSets`. No single permission set should bundle user-level and administrative access in a flat structure.
|
||||
|
||||
|
|
@ -19,87 +27,69 @@ Permission sets in CURABIS apps must be structured in access tiers following the
|
|||
|
||||
## Implementation Pattern
|
||||
|
||||
```al
|
||||
permissionset 50100 "PM365 - View"
|
||||
{
|
||||
Access = Public;
|
||||
Assignable = true;
|
||||
Caption = 'Project Mgmt 365 - View';
|
||||
Permissions =
|
||||
tabledata "PM Project" = R,
|
||||
tabledata "PM Project Task" = R,
|
||||
page "PM Project List" = X,
|
||||
page "PM Project Card" = X;
|
||||
}
|
||||
permissionset 50100 "PM365 - View"
|
||||
{
|
||||
Access = Public;
|
||||
Assignable = true;
|
||||
Caption = 'Project Mgmt 365 - View';
|
||||
Permissions =
|
||||
tabledata "PM Project" = R,
|
||||
page "PM Project List" = X;
|
||||
}
|
||||
|
||||
permissionset 50101 "PM365 - Edit"
|
||||
{
|
||||
Access = Public;
|
||||
Assignable = true;
|
||||
Caption = 'Project Mgmt 365 - Edit';
|
||||
IncludedPermissionSets = "PM365 - View";
|
||||
Permissions =
|
||||
tabledata "PM Project" = RIMD,
|
||||
tabledata "PM Project Task" = RIMD,
|
||||
codeunit "PM Project Management" = X;
|
||||
}
|
||||
permissionset 50101 "PM365 - Edit"
|
||||
{
|
||||
Access = Public;
|
||||
Assignable = true;
|
||||
Caption = 'Project Mgmt 365 - Edit';
|
||||
IncludedPermissionSets = "PM365 - View";
|
||||
Permissions =
|
||||
tabledata "PM Project" = RIMD,
|
||||
tabledata "PM Project Task" = RIMD,
|
||||
codeunit "PM Project Management" = X;
|
||||
}
|
||||
|
||||
permissionset 50102 "PM365 - Admin"
|
||||
{
|
||||
Access = Public;
|
||||
Assignable = false;
|
||||
Caption = 'Project Mgmt 365 - Admin';
|
||||
IncludedPermissionSets = "PM365 - Edit";
|
||||
Permissions =
|
||||
tabledata "PM Setup" = RIMD,
|
||||
page "PM Setup" = X;
|
||||
}
|
||||
```
|
||||
permissionset 50102 "PM365 - Admin"
|
||||
{
|
||||
Access = Public;
|
||||
Assignable = false;
|
||||
Caption = 'Project Mgmt 365 - Admin';
|
||||
IncludedPermissionSets = "PM365 - Edit";
|
||||
Permissions =
|
||||
tabledata "PM Setup" = RIMD,
|
||||
page "PM Setup" = X;
|
||||
}
|
||||
|
||||
## Relationship to CURABIS-ARCH-011
|
||||
|
||||
This rule is a **companion to CURABIS-ARCH-011** (`exposed-objects-must-be-in-a-permission-set`):
|
||||
|
||||
- **CURABIS-ARCH-011**: Every exposed object *must exist* in at least one permission set
|
||||
- **This rule**: Permission sets *themselves* must follow the hierarchical least-privilege structure
|
||||
|
||||
Both must be satisfied simultaneously: it is not enough that objects appear in a permission set if that set grants excessive access.
|
||||
Companion to **CURABIS-ARCH-011** (`exposed-objects-must-be-in-a-permission-set`):
|
||||
ARCH-011 requires every exposed object to *exist* in a permission set; this rule
|
||||
requires the sets *themselves* to follow the tiered least-privilege structure.
|
||||
Both must hold — objects in a set that grants excessive access is not enough.
|
||||
|
||||
## Anti-Pattern
|
||||
|
||||
```al
|
||||
// Violation: flat "full access" set bundles user and admin access
|
||||
permissionset 50100 "PM365 - Full Access"
|
||||
{
|
||||
Assignable = true;
|
||||
Permissions =
|
||||
tabledata "PM Project" = RIMD,
|
||||
tabledata "PM Setup" = RIMD, // admin data mixed with user data
|
||||
tabledata "PM Project Task" = RIMD,
|
||||
codeunit "PM Post Codeunit" = X;
|
||||
}
|
||||
```
|
||||
// Violation: flat "full access" set bundles user and admin access
|
||||
permissionset 50100 "PM365 - Full Access"
|
||||
{
|
||||
Assignable = true;
|
||||
Permissions =
|
||||
tabledata "PM Project" = RIMD,
|
||||
tabledata "PM Setup" = RIMD, // admin data mixed with user data
|
||||
tabledata "PM Project Task" = RIMD,
|
||||
codeunit "PM Post Codeunit" = X;
|
||||
}
|
||||
|
||||
## BCApps Reference
|
||||
|
||||
BCApps Business Foundation defines exactly this tiered pattern:
|
||||
|
||||
```al
|
||||
// BusFoundEdit.PermissionSet.al
|
||||
permissionset 4 "Bus. Found. - Edit"
|
||||
{
|
||||
Access = Public;
|
||||
Assignable = true;
|
||||
Caption = 'Business Foundation - Edit';
|
||||
IncludedPermissionSets = "Bus. Found. - View";
|
||||
}
|
||||
```
|
||||
|
||||
Microsoft uses Admin, Edit, View, Obj, and Read tiers with `IncludedPermissionSets` throughout BCApps — never a single flat "full access" set.
|
||||
BCApps Business Foundation defines exactly this tiered pattern: Microsoft uses
|
||||
Admin, Edit, View, Obj, and Read tiers with `IncludedPermissionSets` throughout —
|
||||
never a single flat "full access" set. Each tier inherits from the tier below;
|
||||
Admin sets use `Assignable = false` to prevent accidental assignment to regular
|
||||
users.
|
||||
|
||||
- **Source:** https://github.com/microsoft/BCApps/tree/main/src/Business%20Foundation/App/Permissions
|
||||
- **Files:** `BusFoundAdmin`, `BusFoundEdit`, `BusFoundView`, `BusFoundObj`, `BusFoundRead`
|
||||
- **Pattern:** Each tier inherits from the tier below via `IncludedPermissionSets`. Admin sets use `Assignable = false` to prevent accidental assignment to regular users.
|
||||
|
||||
## Verification
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
---
|
||||
name: shared-project-memory-must-be-in-repo
|
||||
description: >
|
||||
Project-level memory (business rules, architectural decisions, scope boundaries)
|
||||
must be stored in a version-controlled projectmemory/ folder, not in a user's
|
||||
local Claude memory store, so all team members benefit from shared knowledge.
|
||||
layer: 2
|
||||
category: architecture
|
||||
bc-version: [all]
|
||||
domain: architecture
|
||||
keywords: [projectmemory, shared-memory, repo, team-knowledge]
|
||||
technologies: [al]
|
||||
countries: [w1]
|
||||
application-area: [all]
|
||||
---
|
||||
|
||||
# Shared Project Memory Must Be in the Repository
|
||||
|
|
@ -22,39 +21,33 @@ a different machine. Version-controlled memory is shared, attributed, and persis
|
|||
|
||||
## Anti Pattern
|
||||
|
||||
```
|
||||
# Stored only on Michael's laptop — Tod and SJG never see this
|
||||
~/.claude/projects/d--MyProject/memory/project-pricing-vat-scope.md
|
||||
```
|
||||
# Stored only on Michael's laptop — Tod and SJG never see this
|
||||
~/.claude/projects/d--MyProject/memory/project-pricing-vat-scope.md
|
||||
|
||||
A rule observed by one developer stays siloed. The next session on another machine —
|
||||
or by another team member — starts from zero.
|
||||
|
||||
## Best Practice
|
||||
|
||||
```
|
||||
# In the git repository — committed, shared, visible to all
|
||||
projectmemory/
|
||||
memoryupdates_mid.md ← Michael's observations
|
||||
memoryupdates_tod.md ← Tod's observations
|
||||
memoryupdates_sjg.md ← SJG's observations
|
||||
```
|
||||
# In the git repository — committed, shared, visible to all
|
||||
projectmemory/
|
||||
memoryupdates_mid.md ← Michael's observations
|
||||
memoryupdates_tod.md ← Tod's observations
|
||||
memoryupdates_sjg.md ← SJG's observations
|
||||
|
||||
Each file is named after the user who triggered the observation. All files are read
|
||||
by every team member's Claude session at start, via an instruction in `CLAUDE.md`:
|
||||
|
||||
```markdown
|
||||
## Shared project memory
|
||||
## Shared project memory
|
||||
|
||||
At session start, read **all files** in `projectmemory/` — they contain shared
|
||||
project observations from all team members and are version-controlled in git.
|
||||
At session start, read **all files** in `projectmemory/` — they contain shared
|
||||
project observations from all team members and are version-controlled in git.
|
||||
|
||||
When you learn something project-relevant, write it to
|
||||
`projectmemory/memoryupdates_<username>.md` for the active user.
|
||||
When you learn something project-relevant, write it to
|
||||
`projectmemory/memoryupdates_<username>.md` for the active user.
|
||||
|
||||
User-specific preferences (tone, workflow habits) stay in the local
|
||||
`~/.claude/projects/.../memory/` folder as before.
|
||||
```
|
||||
User-specific preferences (tone, workflow habits) stay in the local
|
||||
`~/.claude/projects/.../memory/` folder as before.
|
||||
|
||||
## What belongs in projectmemory vs local memory
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
bc-version: [all]
|
||||
domain: architecture
|
||||
keywords: [xliff, translation, xlf, caption, tooltip, enu, da-dk, de-de, no-nb, sv-se, de-at]
|
||||
keywords: [xliff, translation, xlf, caption, tooltip, enu, da-dk, de-de, no-nb, sv-se]
|
||||
technologies: [al]
|
||||
countries: [w1]
|
||||
application-area: [all]
|
||||
|
|
@ -51,13 +51,11 @@ The following must remain in English in all locales:
|
|||
|
||||
## Trans-unit structure
|
||||
|
||||
```xml
|
||||
<trans-unit id="..." size-unit="char" translate="yes" xml:space="preserve">
|
||||
<source>Post</source>
|
||||
<target state="translated">Bogfør</target> ← da-DK example
|
||||
<note from="Developer" annotates="source" priority="2">Button caption</note>
|
||||
</trans-unit>
|
||||
```
|
||||
<trans-unit id="..." size-unit="char" translate="yes" xml:space="preserve">
|
||||
<source>Post</source>
|
||||
<target state="translated">Bogfør</target> ← da-DK example
|
||||
<note from="Developer" annotates="source" priority="2">Button caption</note>
|
||||
</trans-unit>
|
||||
|
||||
State must always be `translated` — never `needs-translation` or `new`.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue