Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
967a3aa
fix: update scrutiny areas for draft edit concurrency and renumber se…
johlju Apr 24, 2026
893635c
feat: add expectedEditedAt handling and stale edit conflict notificat…
johlju Apr 24, 2026
c23903b
fix: reject stale draft edits to maintain content integrity
johlju Apr 24, 2026
7c1fc82
feat: add expectedEditedAt handling and stale edit conflict managemen…
johlju Apr 24, 2026
e6f2ced
fix: enhance optimistic concurrency handling for edited_at updates in…
johlju Apr 24, 2026
0c427c3
fix: clarify draft editing requirements and stale draft rejection in …
johlju Apr 24, 2026
0f494cf
fix: document requirement.expectedEditedAt usage and stale token hand…
johlju Apr 24, 2026
1317e86
fix: clarify requirement management edit process and handle stale edi…
johlju Apr 24, 2026
666436c
feat: add revision_token to requirement_versions for optimistic concu…
johlju Apr 25, 2026
5aa30f7
fix: add MCP Tool Contract upkeep instructions for callable behavior …
johlju Apr 25, 2026
ab43b38
fix: replace expectedEditedAt with baseRevisionToken and baseVersionI…
johlju Apr 25, 2026
5d0afc3
fix: update draft edit concurrency scenario to include baseVersionId …
johlju Apr 25, 2026
26d8764
fix: replace expectedEditedAt with baseRevisionToken and baseVersionI…
johlju Apr 25, 2026
67c52ad
fix: replace expectedEditedAt with baseRevisionToken and baseVersionI…
johlju Apr 25, 2026
867448b
fix: update requirement editing logic to use baseVersionId and baseRe…
johlju Apr 25, 2026
c6efaf4
fix: refactor UP_STATEMENTS for clarity and structure in requirement_…
johlju Apr 25, 2026
aa73057
fix: update documentation to reflect changes in concurrency handling …
johlju Apr 25, 2026
9c837a2
fix: enhance requirement form with refresh handling and loading state
johlju Apr 25, 2026
6b36271
fix: update editRequirement logic to use review and archived version …
johlju Apr 25, 2026
077b6e9
fix: enhance requirement tests to handle stale edit conflicts and err…
johlju Apr 25, 2026
a1cbaf3
fix: comment out SQL Server env file preparation step in integration …
johlju Apr 25, 2026
efcb020
fix: uncomment SQL Server env file preparation step in integration tests
johlju Apr 25, 2026
c324df2
debug CI
johlju Apr 25, 2026
6f69e78
fix: comment out sensitive environment variable setup in SQL Server p…
johlju Apr 25, 2026
4546d44
debug ci
johlju Apr 25, 2026
986fe5c
fix: re-add MSSQL_SA_PASSWORD for integration tests in CI
johlju Apr 25, 2026
7b1c945
fix: add readonly database user credentials for integration tests
johlju Apr 25, 2026
e295fa5
fix: remove sensitive environment variables from SQL Server setup in …
johlju Apr 25, 2026
cda25d5
fix: remove sensitive information from SQL Server environment setup i…
johlju Apr 25, 2026
e5c3a56
fix: update SQL Server environment variables for consistency across c…
johlju Apr 25, 2026
bf0ceee
fix: update comments in SQL Server CI environment file for clarity
johlju Apr 25, 2026
48177f7
fix: refactor tool retrieval to use getTool function and update revis…
johlju Apr 25, 2026
10196c4
fix: update revision_token constraint to be unique in requirement_ver…
johlju Apr 25, 2026
9c262f8
fix: enhance check script to include dotenv-linter checks and fixes
johlju Apr 25, 2026
dd4dba5
fix: update check and fix commands to include dotenv-linter functiona…
johlju Apr 25, 2026
4ac483d
fix: add dotenv:check command to the check script
johlju Apr 25, 2026
60aa7ab
fix: add dotenv-linter installation and check to quality checks workflow
johlju Apr 25, 2026
32b429e
fix: install dotenv-linter for environment file checks in Dockerfile
johlju Apr 25, 2026
c33be29
fix: add dotenv-linter information to architecture documentation
johlju Apr 25, 2026
a9ac879
fix: update dotenv-linter checks in quality workflow with improved fl…
johlju Apr 25, 2026
d50f6b1
fix: enhance dotenv-linter commands with exclusions for improved chec…
johlju Apr 25, 2026
7370771
fix: simplify getTool function by removing cleanup handling and strea…
johlju Apr 25, 2026
1f1b784
fix: remove unnecessary exclusion flag from dotenv-linter devcontaine…
johlju Apr 25, 2026
2dca9c8
fix: refactor tool retrieval logic in MCP tests for improved resource…
johlju Apr 25, 2026
988fedf
fix: streamline dotenv-linter flags and optimize test tool retrieval
johlju Apr 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions .devcontainer/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,16 @@ MSSQL_PID=Developer
MSSQL_SA_PASSWORD=YourStrong!Passw0rd
SQLSERVER_HOST_PORT=1433

DATABASE_READONLY_PASSWORD_ENV=DB_READONLY_PASSWORD
DB_ENCRYPT=true
DB_HOST=db
DB_PORT=1433
DB_NAME=kravhantering
DB_READONLY_USER=readonly
DB_PORT=1433
DB_READONLY_PASSWORD=BrowseOnly!Passw0rd7
DATABASE_READONLY_PASSWORD_ENV=DB_READONLY_PASSWORD
DB_ENCRYPT=true
DB_READONLY_USER=readonly
DB_TRUST_SERVER_CERTIFICATE=true
NODE_ENV=development
NEXT_TELEMETRY_DISABLED=1
NODE_ENV=development

# Optional explicit overrides for the derived DB_* connection settings above:
# DATABASE_URL=mssql://sa:YourStrong!Passw0rd@db:1433/kravhantering?encrypt=true&trustServerCertificate=true
Expand Down
4 changes: 4 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ RUN apt-get update && \
mkcert && \
rm -rf /var/lib/apt/lists/*

# Install dotenv-linter for env file checks.
RUN curl -sSfL https://raw.githubusercontent.com/dotenv-linter/dotenv-linter/master/install.sh | \
sh -s -- -b /usr/local/bin

# Set the working directory
WORKDIR /workspace

Expand Down
14 changes: 7 additions & 7 deletions .env.development
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,31 @@
# Development-only HMAC secret (intentionally public, non-production value)
ANALYTICS_HASH_SECRET=dev-local-secret-not-for-production

DB_ENCRYPT=true
# Local SQL Server defaults for host-based development.
# The devcontainer injects its own DB_* values from `.devcontainer/.env`,
# and those existing shell variables take precedence over these committed
# defaults when the app runs inside the container.
DB_HOST=127.0.0.1
DB_PORT=1433
DB_NAME=kravhantering
MSSQL_SA_PASSWORD=YourStrong!Passw0rd
DB_READONLY_USER=readonly
DB_PORT=1433
DB_READONLY_PASSWORD=BrowseOnly!Passw0rd7
DB_ENCRYPT=true
DB_READONLY_USER=readonly
DB_TRUST_SERVER_CERTIFICATE=true
MSSQL_SA_PASSWORD=YourStrong!Passw0rd

NEXTJS_ENV=development
NEXT_PUBLIC_SITE_URL=http://localhost:3000

AUTH_OIDC_CLIENT_ID=kravhantering-app
AUTH_OIDC_CLIENT_SECRET=dev-only-app-secret
# --------------------------------------
# Authentication (PhenixID OIDC) — local dev defaults targeting the local
# Keycloak realm. See docs/auth-developer-workflow.md.
# --------------------------------------
AUTH_OIDC_ISSUER_URL=http://localhost:8080/realms/kravhantering-dev
AUTH_OIDC_CLIENT_ID=kravhantering-app
AUTH_OIDC_CLIENT_SECRET=dev-only-app-secret
AUTH_OIDC_REDIRECT_URI=http://localhost:3000/api/auth/callback
AUTH_OIDC_POST_LOGOUT_REDIRECT_URI=http://localhost:3000/
AUTH_OIDC_REDIRECT_URI=http://localhost:3000/api/auth/callback
# Iron-session cookie key (≥32 chars). Dev-only fixed value so every
# contributor gets a working setup without manual generation. Real envs
# generate this with `openssl rand -base64 48` and store it in a Secret.
Expand Down
14 changes: 7 additions & 7 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -87,26 +87,26 @@ AUTH_ENABLED=true
# without a server round-trip.
NEXT_PUBLIC_AUTH_ENABLED=true

AUTH_OIDC_CLIENT_ID=kravhantering-app
AUTH_OIDC_CLIENT_SECRET=dev-only-app-secret
# OIDC issuer base URL (used for discovery at <ISSUER>/.well-known/openid-configuration).
# Local Keycloak default: http://localhost:8080/realms/kravhantering-dev
AUTH_OIDC_ISSUER_URL=http://localhost:8080/realms/kravhantering-dev
AUTH_OIDC_CLIENT_ID=kravhantering-app
AUTH_OIDC_CLIENT_SECRET=dev-only-app-secret

AUTH_OIDC_POST_LOGOUT_REDIRECT_URI=http://localhost:3000/
# Full callback URL, must be pre-registered with the IdP.
AUTH_OIDC_REDIRECT_URI=http://localhost:3000/api/auth/callback
AUTH_OIDC_POST_LOGOUT_REDIRECT_URI=http://localhost:3000/

# Optional. Defaults shown.
AUTH_OIDC_SCOPES=openid profile email
AUTH_OIDC_ROLES_CLAIM=roles
# Audience expected on access tokens (MCP). Defaults to AUTH_OIDC_CLIENT_ID.
AUTH_OIDC_API_AUDIENCE=
AUTH_OIDC_ROLES_CLAIM=roles
# Optional. Defaults shown.
AUTH_OIDC_SCOPES="openid profile email"

AUTH_SESSION_COOKIE_NAME=kravhantering_session
# Iron-session encryption password. MUST be at least 32 characters.
# Generate with: openssl rand -base64 48
AUTH_SESSION_COOKIE_PASSWORD=replace-with-32-bytes-of-randomness-XXXXXXXX
AUTH_SESSION_COOKIE_NAME=kravhantering_session
AUTH_SESSION_TTL_SECONDS=28800

# When the app runs behind a reverse proxy (OpenShift Route, ingress),
Expand Down
24 changes: 17 additions & 7 deletions .env.sqlserver.ci
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
# CI defaults for integration tests (no secrets — safe to commit).
# MSSQL_SA_PASSWORD must be supplied by the CI runner (GitHub Actions
# variable / secret) and appended to .env.sqlserver before `npm run db:up`.
# Read-only browse credentials are intentionally omitted; CI only needs
# the SA login to provision the database and run integration tests.
# CI defaults for integration tests and browse workflows (safe to commit).
# MSSQL_SA_PASSWORD is a well-known SQL Server example password intentionally
# committed because forked PRs cannot access GitHub Actions secrets or vars.
# The read-only credentials block is also committed for integration tests and
# read-only developer browse use.

ACCEPT_EULA=Y
MSSQL_PID=Developer
SQLSERVER_HOST_PORT=1433

# This password is a well-known password (used in examples) to build the test
# database and run integration tests in CI. It is intentionally set here and not
# a secret or variable in GitHub Actions because the integration tests need to
# run on pull requests from forks, where secrets and variables are not available.
MSSQL_SA_PASSWORD=YourStrong!Passw0rd

DB_ENCRYPT=true
DB_HOST=127.0.0.1
DB_PORT=1433
DB_NAME=kravhantering
DB_ENCRYPT=true
DB_PORT=1433
DB_TRUST_SERVER_CERTIFICATE=true

DATABASE_READONLY_PASSWORD_ENV=DB_READONLY_PASSWORD
DB_READONLY_PASSWORD=BrowseOnly!Passw0rd7
DB_READONLY_USER=readonly
8 changes: 4 additions & 4 deletions .env.sqlserver.example
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ MSSQL_PID=Developer
MSSQL_SA_PASSWORD=YourStrong!Passw0rd
SQLSERVER_HOST_PORT=1433

DATABASE_READONLY_PASSWORD_ENV=DB_READONLY_PASSWORD
DB_ENCRYPT=true
DB_HOST=127.0.0.1
DB_PORT=1433
DB_NAME=kravhantering
DB_READONLY_USER=readonly
DB_PORT=1433
DB_READONLY_PASSWORD=BrowseOnly!Passw0rd7
DATABASE_READONLY_PASSWORD_ENV=DB_READONLY_PASSWORD
DB_ENCRYPT=true
DB_READONLY_USER=readonly
DB_TRUST_SERVER_CERTIFICATE=true

# Optional explicit overrides for the derived DB_* connection settings above:
Expand Down
3 changes: 2 additions & 1 deletion .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
## Commands

- `npm run check` - all checks (`type-check`, `lint:py`,
`format:check`, `spell:check`, `lint`, `lint:md`, `test`)
`dotenv:check`, `format:check`, `spell:check`, `lint`, `lint:md`,
`test`)
- `npm run test` - run tests
- `npm run dev` - start dev server

Expand Down
20 changes: 20 additions & 0 deletions .github/instructions/mcp-tool-contract.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
applyTo: "{lib/mcp/**/*.ts,lib/requirements/**/*.ts,lib/dal/**/*.ts,app/api/**/*.ts,docs/mcp-server-*.md,tests/unit/mcp-http.test.ts}"
---

# MCP Tool Contract Upkeep

## When Changing Callable Behavior

- If logic changes what an MCP client must send, can receive, or should do
next, update `lib/mcp/server.ts` in the same change.
- Keep tool `description`, `inputSchema`, `outputSchema`, and field
`.describe(...)` text aligned with the handler/service behavior.
- State prerequisite tool calls and exact source/destination fields for values
clients must echo, such as `requirements_get_requirement`
`requirement.versions[0].id` to `requirement.baseVersionId`.
- Do not rely on user docs alone to teach MCP clients how to call a tool.
- Update `docs/mcp-server-user-guide.md`,
`docs/mcp-server-contributor-guide.md`, and `tests/unit/mcp-http.test.ts`.
- For outward-facing MCP invariants, update the quality siblings described in
`.github/instructions/quality-spec.instructions.md`.
32 changes: 22 additions & 10 deletions .github/skills/run-spec-audit/references/scrutiny-areas.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,19 @@ maintenance rule.
- **Verify:** `npm exec -- vitest run tests/quality/functional.test.ts
-t "Scenario 4"`

## 5. Package-Local Requirements and Deviations — Scenario 6, 7
## 5. Draft Edit Concurrency — Scenario 11

- **Code:** `lib/dal/requirements.ts` and
`lib/requirements/service.ts` — `baseVersionId`/`baseRevisionToken`
optimistic edit preconditions.
- **Spec:** `docs/lifecycle-workflow.md`.
- **Req tag:** `[Req: formal — docs/lifecycle-workflow.md "Draft"]`
- **Question:** Are stale draft edits rejected before content or joins are
rewritten?
- **Verify:** `npm exec -- vitest run tests/quality/functional.test.ts
-t "Scenario 11"`

Comment thread
coderabbitai[bot] marked this conversation as resolved.
## 6. Package-Local Requirements and Deviations — Scenario 6, 7

- **Code:** `lib/dal/requirement-packages.ts` — package-local
requirement, needs-reference, and deviation-gated status functions.
Expand All @@ -73,7 +85,7 @@ maintenance rule.
- **Verify (S7):** `npm exec -- vitest run
tests/quality/functional.test.ts -t "Scenario 7"`

## 6. Deviation Lifecycle Guards and Decision Immutability — Scenario 9
## 7. Deviation Lifecycle Guards and Decision Immutability — Scenario 9

- **Code:** `lib/dal/deviations.ts` — approval/rejection logic,
review-requested guards, edit/delete guards.
Expand All @@ -87,7 +99,7 @@ maintenance rule.
- **Verify:** `npm exec -- vitest run tests/quality/functional.test.ts
-t "Scenario 9"`

## 7. Suggestion Terminal State — Scenario 8
## 8. Suggestion Terminal State — Scenario 8

- **Code:** `lib/dal/improvement-suggestions.ts` — resolution logic.
- **Spec:** `docs/lifecycle-workflow.md`.
Expand All @@ -98,15 +110,15 @@ maintenance rule.
- **Verify:** `npm exec -- vitest run tests/quality/functional.test.ts
-t "Scenario 8"`

## 8. List View Defensive Parsing
## 9. List View Defensive Parsing

- **Code:** `lib/requirements/list-view.ts`.
- **Spec:** `docs/requirements-ui-behaviour.md` and
`docs/admin-center.md`.
- **Question:** Do malformed admin defaults, invalid visible-column
JSON, hidden filters, or bad widths fail safely?

## 9. REST and MCP Output Consistency
## 10. REST and MCP Output Consistency

- **Code:** `lib/mcp/http.ts`, `lib/mcp/server.ts`,
`app/api/requirements/[id]/route.ts`,
Expand All @@ -118,7 +130,7 @@ maintenance rule.
- **Question:** Do REST and MCP outputs, transport rules, and field
names match the documentation and field contracts?

## 10. CSV Export
## 11. CSV Export

- **Code:** `lib/export-csv.ts`.
- **Spec:** `docs/reports.md`.
Expand All @@ -127,15 +139,15 @@ maintenance rule.
- **Question:** Does export behavior match the documented CSV
expectations for separators and escaping?

## 11. Coverage Target Alignment
## 12. Coverage Target Alignment

- **Source:** `tests/quality/QUALITY.md` — Coverage Targets table.
- **Question:** Do the subsystems and file paths listed in the
coverage-targets table still match the actual project structure?
Flag new DAL files, renamed modules, or removed subsystems that
make the targets stale.

## 12. MCP Tool Inventory Parity — Scenario 10
## 13. MCP Tool Inventory Parity — Scenario 10

- **Code:** `lib/mcp/server.ts`.
- **Spec:** `docs/mcp-server-contributor-guide.md` ("Server Contract",
Expand All @@ -161,7 +173,7 @@ This file must stay in sync with `tests/quality/QUALITY.md`:
references here.
- See `tests/quality/AGENTS.md` for the authoritative sync rule.

## 13. Reference Data Behavioral Contracts
## 14. Reference Data Behavioral Contracts

- **Code:** `lib/dal/norm-references.ts`, `lib/dal/owners.ts`,
`lib/dal/package-implementation-types.ts`,
Expand All @@ -176,7 +188,7 @@ This file must stay in sync with `tests/quality/QUALITY.md`:
(`nameSv` for taxonomy, `normReferenceId` for norm
references, `lastName`/`firstName` for owners)?

## 14. AI Generation Contracts
## 15. AI Generation Contracts

- **Code:** `lib/ai/openrouter-client.ts`,
`lib/ai/requirement-prompt.ts`, `lib/ai/taxonomy.ts`.
Expand Down
19 changes: 0 additions & 19 deletions .github/workflows/integration-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,25 +52,12 @@ jobs:
- name: Prepare SQL Server env file
run: |
cp .env.sqlserver.ci .env.sqlserver
# This uses a well-known password from examples, but it's stored as a
# GitHub Actions variable to avoid hitting any security scanners that
# look for hardcoded secrets.
echo "MSSQL_SA_PASSWORD=${MSSQL_SA_PASSWORD}" >> .env.sqlserver
env:
MSSQL_SA_PASSWORD: ${{ vars.MSSQL_SA_PASSWORD }}

- name: Start local database service
run: npm run db:up

- name: Setup local SQL Server database
run: npm run db:setup
env:
MSSQL_SA_PASSWORD: ${{ vars.MSSQL_SA_PASSWORD }}
DB_HOST: 127.0.0.1
DB_PORT: 1433
DB_NAME: kravhantering
DB_ENCRYPT: 'true'
DB_TRUST_SERVER_CERTIFICATE: 'true'

- name: Install Playwright Browsers
run: npx playwright install --with-deps chromium
Expand All @@ -79,12 +66,6 @@ jobs:
run: ${{ matrix.testCommand }}
env:
CI: true
MSSQL_SA_PASSWORD: ${{ vars.MSSQL_SA_PASSWORD }}
DB_HOST: 127.0.0.1
DB_PORT: 1433
DB_NAME: kravhantering
DB_ENCRYPT: 'true'
DB_TRUST_SERVER_CERTIFICATE: 'true'

- name: Upload test results (${{ matrix.server }})
if: always()
Expand Down
18 changes: 17 additions & 1 deletion .github/workflows/quality-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ on:

permissions:
contents: read
checks: write
pull-requests: write

jobs:
Expand Down Expand Up @@ -45,6 +46,20 @@ jobs:
- name: Run Python type check
run: npm run lint:py

- name: Run dotenv-linter root check
uses: dotenv-linter/action-dotenv-linter@v3
with:
dotenv_linter_flags: .
filter_mode: nofilter
fail_level: any

- name: Run dotenv-linter devcontainer check
uses: dotenv-linter/action-dotenv-linter@v3
with:
dotenv_linter_flags: .devcontainer --recursive
filter_mode: nofilter
fail_level: any
Comment thread
coderabbitai[bot] marked this conversation as resolved.

- name: Run tests and coverage
run: npm run test:coverage

Expand Down Expand Up @@ -84,7 +99,8 @@ jobs:
{ name: 'Lint', command: 'npm run lint' },
{ name: 'Markdown Lint', command: 'npm run lint:md' },
{ name: 'Type Check', command: 'npm run type-check' },
{ name: 'Python Type Check', command: 'npm run lint:py' }
{ name: 'Python Type Check', command: 'npm run lint:py' },
{ name: 'dotenv-linter', command: 'npm run dotenv:check' }
];

let body = '❌ **Quality checks failed!** Please fix the following issues:\n\n';
Expand Down
6 changes: 4 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ for setup, migrations, and the read-only browse workflow.
| `npm run start:prodlike` | Rebuild and start the prod-like app on port 3001 (`NODE_ENV=production`) |
| `npm run build` | Production build |
| `npm run start` | Start the production server |
| `npm run check` | Run all checks (TS, Python, format, lint, tests) |
| `npm run check` | Run all checks (TS, Python, dotenv, format, lint, tests) |
| `npm run test` | Run unit tests with Vitest |
| `npm run test:watch` | Run unit tests in watch mode |
| `npm run test:coverage` | Run unit tests with coverage |
Expand All @@ -39,10 +39,12 @@ for setup, migrations, and the read-only browse workflow.
| `npm run lint` | Lint with Biome |
| `npm run lint:fix` | Lint and auto-fix with Biome |
| `npm run lint:py` | Type-check Python scripts with Pyright |
| `npm run dotenv:check` | Check dotenv files with dotenv-linter |
| `npm run dotenv:fix` | Auto-fix dotenv files with dotenv-linter |
| `npm run format` | Format code with Biome |
| `npm run spell` | Spell check with cspell |
| `npm run lint:md` | Lint Markdown files |
| `npm run fix` | Auto-fix formatting, linting & Markdown |
| `npm run fix` | Auto-fix formatting, linting, Markdown, and dotenv files |
| `npm run type-check` | TypeScript type checking |
<!-- markdownlint-enable MD013 -->

Expand Down
Loading
Loading