Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
7b87ef5
chore(release): sync beta back into development
github-actions[bot] Aug 31, 2026
def6ad7
Merge pull request #1431 from ConductionNL/sync/beta-to-development-0…
rubenvdlinde Aug 31, 2026
11f29ea
chore(release): 0.2.10-unstable.20260831134103 (#1433)
github-actions[bot] Aug 31, 2026
28d92b5
fix(deps): make the npm overrides follow their direct dependency (#1434)
rubenvdlinde Aug 31, 2026
3118cf3
chore(release): 0.2.11-unstable.20260831163701 (#1435)
github-actions[bot] Aug 31, 2026
572a59d
chore(icons): adopt the Tier B vocabulary, except where the data says…
rubenvdlinde Aug 31, 2026
7088b8e
chore(register): retire the example schema, rename Project to engagem…
rubenvdlinde Sep 1, 2026
de46d22
fix(bbv): drop the second Refresh, and wire the one that stays (#1440)
rubenvdlinde Sep 1, 2026
c9bfb4a
feat(reports): finish the move, and retire the six duplicate menu ent…
rubenvdlinde Sep 1, 2026
c7c6fd5
chore(release): 0.2.12-unstable.20260901050759 (#1443)
github-actions[bot] Sep 1, 2026
4da54fe
docs(openspec): deprecate booked hours in shillinq, lean on humaniq
rubenvdlinde Sep 1, 2026
9acd039
fix(mock): drop the three seed objects bound to the retired example s…
rubenvdlinde Sep 1, 2026
18bdeb4
chore(lint): let the linter see tests/ and scripts/ (#1446)
rubenvdlinde Sep 1, 2026
ae11c4b
Merge pull request #1447 from ConductionNL/feat/hours-to-humaniq
rubenvdlinde Sep 1, 2026
99d7717
fix(router): resolve deep links in both URL forms (#1451)
rubenvdlinde Sep 1, 2026
70ba77f
Takes nextcloud-vue 2.31.1 so a hovered KPI tile stops drawing a card…
rubenvdlinde Sep 2, 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
2 changes: 1 addition & 1 deletion appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Vrij en open source onder de EUPL-1.2-licentie.

**Ondersteuning:** Voor ondersteuning, neem contact op via support@conduction.nl.
]]></description>
<version>0.2.9-unstable.20260831013830</version>
<version>0.2.12-unstable.20260901050759</version>
<licence>EUPL-1.2</licence>
<author mail="info@conduction.nl" homepage="https://www.conduction.nl/">Conduction</author>
<namespace>Shillinq</namespace>
Expand Down
141 changes: 133 additions & 8 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -144,11 +144,32 @@ export default [
'no-console': 'off',
'n/no-process-exit': 'off',
'n/hashbang': 'off',
// `_` / `__` as a deliberate throwaway binding — `catch (_)`, a
// discarded destructuring slot. Narrow on purpose: the pattern matches
// UNDERSCORES ONLY, so a real name that happens to start with `_` is
// still reported. v9 drives plain `.js` through the CORE rule (the
// `@typescript-eslint` swap is per-file-type), so it is set here.
// Tests import devDependencies by definition; this rule is about what
// ships in the published package, which tests/ never does.
'n/no-unpublished-import': 'off',
},
},

{
// `_` / `__` as a deliberate throwaway binding — `catch (_)`, a discarded
// destructuring slot. Narrow on purpose: the pattern matches UNDERSCORES
// ONLY, so a real name that happens to start with `_` is still reported.
//
// 🔴 `.js` / `.mjs` ONLY, NOT `.ts`. The CORE rule is not TypeScript-aware:
// applied to a `.ts` file it reads the parameter NAMES inside a function
// TYPE as bindings and reports them unused. Measured on humaniq —
//
// t?: (app: string, key: string) => string
//
// produced four `no-unused-vars` errors for `app` and `key`, which are
// documentation, not variables. The same mis-scoping made every unused
// `catch (e)` in a `.ts` spec report TWICE, once per rule.
//
// v9 already turns the core rule off for `.ts` and drives
// `@typescript-eslint/no-unused-vars` instead; naming `.ts` here switched
// it back on. TypeScript files are handled by the block below.
files: ['tests/**/*.js', 'tests/**/*.mjs'],
rules: {
'no-unused-vars': [
'error',
{
Expand All @@ -165,12 +186,116 @@ export default [
ignoreRestSiblings: true,
},
],
// Tests import devDependencies by definition; this rule is about what
// ships in the published package, which tests/ never does.
'n/no-unpublished-import': 'off',
},
},

{
// The TypeScript half of the block above. Same intent, same patterns, on
// the rule that actually understands the language: it knows a name inside
// a function type is not a binding, so type annotations stay quiet while a
// genuinely dead local is still reported.
files: ['tests/**/*.ts', 'tests/**/*.tsx'],
rules: {
'@typescript-eslint/no-unused-vars': [
'error',
{
varsIgnorePattern: '^_+$',
caughtErrors: 'all',
caughtErrorsIgnorePattern: '^_+$',
argsIgnorePattern: '^_',
ignoreRestSiblings: true,
},
],
},
},

{
// 🔴 Node-side CLI tooling under `scripts/`, which is COMMONJS. Flat
// config defaults every `.js` to ESM with browser-ish globals, so without
// this block eslint reports the CommonJS wrapper itself as undefined
// identifiers. Measured on this app: 52 of the 233 errors under
// `tests/` + `scripts/` were `no-undef`, ALL of them in `scripts/`, and
// all five names were the environment rather than a typo — `process` 23,
// `require` 20, `__dirname` 6, `__filename` 2, `module` 1.
//
// This is describing the environment, not relaxing a rule, and it is the
// same argument the test-globals block below makes: declaring them keeps
// `no-undef` able to do its real job, which is catching a genuinely
// misspelled identifier. Suppressing the rule instead would bury that.
//
// `no-console` is off because printing its report is what a CLI checker
// is FOR.
//
// 🔴 NO `n/*` ENTRIES HERE, DELIBERATELY. `eslint-plugin-n` is NOT
// registered for these files under eslint 10 + @nextcloud/eslint-config
// 9, so `'n/no-process-exit': 'off'` would be dead config that reads as
// if it were doing something. Measured both ways on this app: 0 `n/`
// findings with the entries and 0 without.
//
// What DID report was the opposite — four `scripts/*.js` carried
// `/* eslint-disable n/no-process-exit */` and `/* eslint-disable
// n/shebang */` left over from the eslintrc era, and an inline disable
// naming an unregistered plugin is itself an error ("Definition for rule
// 'n/shebang' was not found"). Those 8 comments are removed; do not add
// `n/*` rules back to replace them.
//
// ⚠️ `.js` and `.cjs` ONLY. A `scripts/*.mjs` is genuinely ESM and must
// keep the default `sourceType`, or `import` stops parsing there.
files: ['scripts/**/*.js', 'scripts/**/*.cjs'],
languageOptions: {
sourceType: 'commonjs',
globals: {
require: 'readonly',
module: 'writable',
exports: 'writable',
process: 'readonly',
__dirname: 'readonly',
__filename: 'readonly',
console: 'readonly',
Buffer: 'readonly',
global: 'readonly',
URL: 'readonly',
TextEncoder: 'readonly',
TextDecoder: 'readonly',
},
},
rules: {
'no-console': 'off',
},
},

{
// The ESM half of the block above. A `scripts/*.mjs` is genuinely a module
// and must keep the default `sourceType`, so it gets Node's globals but
// none of the CommonJS wrapper. Measured: `process` reported undefined 2x
// in hermiq's generate-opengemeenten-icons.mjs and 4x in openregister's
// l10n/runtime-check.mjs, which the `.js`/`.cjs` block deliberately does
// not match.
files: ['scripts/**/*.mjs', 'tests/**/*.mjs'],
languageOptions: {
globals: {
process: 'readonly',
console: 'readonly',
Buffer: 'readonly',
global: 'readonly',
URL: 'readonly',
TextEncoder: 'readonly',
TextDecoder: 'readonly',
},
},
rules: {
'no-console': 'off',
},
},

{
// eslint must not try to PARSE a shell script. `tests/e2e/seed.test.sh`
// matches the `**/*.test.*` glob some presets use, and eslint then reads
// it as JavaScript and reports "Parsing error: Unexpected character" —
// a finding about a file it should never have opened.
ignores: ['**/*.sh', '**/*.bash'],
},

{
// Test globals. Several apps keep their spec files INSIDE `src/`, which the
// lint script scans, and neither `@nextcloud/eslint-config` nor the runner
Expand Down
8 changes: 5 additions & 3 deletions lib/Repair/FoldExpensesAndHoursIntoProject.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ public function getName(): string {
* @param IOutput $output The repair-step output (progress + warnings).
*
* @return void
*
* @spec openspec/specs/bookkeeping-consultancy-project-accounting/spec.md
*/
public function run(IOutput $output): void {
try {
Expand All @@ -99,7 +101,7 @@ public function run(IOutput $output): void {
// Index every Project by every identifier a source object might
// reference (id / uuid / projectNumber / code). Values are kept
// as live mutable arrays so multiple lines fold into one save.
$projects = $this->readAllRows(objectService: $this->objectService, registerSlug: $registerSlug, schema: 'Project');
$projects = $this->readAllRows(objectService: $this->objectService, registerSlug: $registerSlug, schema: 'engagement');

if ($projects === []) {
$output->info('Shillinq: no Project records — expense/hours fold skipped.');
Expand Down Expand Up @@ -171,11 +173,11 @@ public function run(IOutput $output): void {
try {
$this->objectService
->setRegister($registerSlug)
->setSchema('Project')
->setSchema('engagement')
->saveObject(
object: $record,
register: $registerSlug,
schema: 'Project',
schema: 'engagement',
_rbac: false,
_multitenancy: false,
);
Expand Down
2 changes: 1 addition & 1 deletion lib/Repair/RematerialiseConvertedCalculations.php
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ class RematerialiseConvertedCalculations implements IRepairStep {
'ZzpDeduction',
'SisaReport',
'InventoryReorderRule',
'Project',
'engagement',
'ProjectAssignment',
'VatReturn',
'InnovatieboxElection',
Expand Down
2 changes: 1 addition & 1 deletion lib/Settings/register.d/000-register-declaration.json
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@
"PricingTier",
"Programma",
"Programmabegroting",
"Project",
"engagement",
"ProjectAssignment",
"ProjectBudget",
"ProvincialeFondsPosting",
Expand Down
2 changes: 1 addition & 1 deletion lib/Settings/register.d/abstract-project-cost-lines.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"x-shillinq-fragment": "abstract-project-cost-lines",
"components": {
"schemas": {
"Project": {
"engagement": {
"version": "0.2.0",
"properties": {
"costLines": {
Expand Down
2 changes: 1 addition & 1 deletion lib/Settings/register.d/add-shillinq-audit-trail.json
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,7 @@
"description": "OR's audit-trail-immutable captures every create / update / lifecycle / delete event on PerDiemRate with actor, timestamp, action, before/after snapshot, and hash chain per ADR-022 + REQ-AT-001..AT-002. Retention is governed by OR per REQ-AT-005 (no shillinq cleanup job)."
}
},
"Project": {
"engagement": {
"x-openregister-audit-trail": {
"enabled": true,
"description": "OR's audit-trail-immutable captures every create / update / lifecycle / delete event on Project with actor, timestamp, action, before/after snapshot, and hash chain per ADR-022 + REQ-AT-001..AT-002. Retention is governed by OR per REQ-AT-005 (no shillinq cleanup job)."
Expand Down
2 changes: 1 addition & 1 deletion lib/Settings/register.d/bookings-deposit-to-invoice.json
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@
},
"Invoice": {
"slug": "Invoice",
"icon": "FileDocumentOutline",
"icon": "ReceiptTextOutline",
"version": "0.1.0",
"title": "Invoice",
"description": "A final customer invoice materialised in Shillinq when a booking order completes. Carries a service line and, when a deposit was authorised, a negative deposit-credit line. Bidirectionally linked to its Order via sourceDocumentUri and to the credited DepositPayment via depositPaymentId (REQ-DI-001). Integrates into Shillinq AR aging with no special handling (REQ-DI-009).",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@
],
"filter": {},
"join": {
"through": "Project",
"through": "engagement",
"on": "Project.code",
"select": [
"Project.name",
Expand Down Expand Up @@ -570,7 +570,7 @@
{
"@self": {
"register": "shillinq",
"schema": "Project",
"schema": "engagement",
"slug": "proj-internal-platform"
},
"code": "PROJ-INT-PLAT",
Expand All @@ -584,7 +584,7 @@
{
"@self": {
"register": "shillinq",
"schema": "Project",
"schema": "engagement",
"slug": "proj-grant-research"
},
"code": "PROJ-GRANT-RND",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"schemas": {
"Employee": {
"slug": "Employee",
"icon": "AccountTie",
"icon": "AccountTieOutline",
"version": "0.1.0",
"title": "Employee",
"description": "Employee / detached worker / freelancer master record (REQ-PAY-001). Carries legal name, BSN (11-proef validated, masked on display per ADR-005), contract classification and onboarding/exit dates. A contact/person is a Nextcloud entity; this register holds the payroll-administration projection only.",
Expand Down Expand Up @@ -211,7 +211,7 @@
},
"Payroll": {
"slug": "Payroll",
"icon": "CashMultiple",
"icon": "CashSync",
"version": "0.1.0",
"title": "Payroll",
"description": "Payroll period sub-ledger record (REQ-PAY-002). Captures gross input and aggregated deduction totals; on issue it materialises a balanced GLTransaction (REQ-PAY-008) per the T1 JournalEntry pattern. UBL Peppol BIS 30 field shape is declared for T4 passthrough but NOT computed here (REQ-PAY-010).",
Expand Down
2 changes: 1 addition & 1 deletion lib/Settings/register.d/zz-order-primitive.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"schemas": {
"OrderPrimitive": {
"slug": "OrderPrimitive",
"icon": "FileDocumentMultipleOutline",
"icon": "ClipboardListOutline",
"version": "0.1.0",
"title": "Order",
"x-schema-org": "schema:Order",
Expand Down
2 changes: 1 addition & 1 deletion lib/Settings/register.d/zzz-mcp-tool-surface.json
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@
}
}
},
"Project": {
"engagement": {
"configuration": {
"x-openregister-mcp": {
"enabled": true,
Expand Down
35 changes: 4 additions & 31 deletions lib/Settings/shillinq_mock_register.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"openapi": "3.0.0",
"info": {
"title": "shillinq demo data",
"version": "1.0.0",
"version": "1.1.0",
"description": "Demo data covering every schema this app supplies, offered as the first step of the app's setup walkthrough. Generated from the schemas themselves, so every object satisfies the schema that will validate it."
},
"x-openregister": {
Expand Down Expand Up @@ -23760,7 +23760,7 @@
{
"@self": {
"register": "shillinq",
"schema": "Project",
"schema": "engagement",
"slug": "project-voorbeeld-name-1-1"
},
"administrationId": "Voorbeeld Administrationid 1",
Expand Down Expand Up @@ -23810,7 +23810,7 @@
{
"@self": {
"register": "shillinq",
"schema": "Project",
"schema": "engagement",
"slug": "project-voorbeeld-name-2-2"
},
"administrationId": "Voorbeeld Administrationid 2",
Expand Down Expand Up @@ -23860,7 +23860,7 @@
{
"@self": {
"register": "shillinq",
"schema": "Project",
"schema": "engagement",
"slug": "project-voorbeeld-name-3-3"
},
"administrationId": "Voorbeeld Administrationid 3",
Expand Down Expand Up @@ -33567,33 +33567,6 @@
"mkbProfitExemptionPercentage": 1.0,
"source": "Voorbeeld Source 3"
},
{
"@self": {
"register": "shillinq",
"schema": "example",
"slug": "example-voorbeeld-title-1-1"
},
"title": "Voorbeeld Title 1",
"description": "Voorbeeld Description 1"
},
{
"@self": {
"register": "shillinq",
"schema": "example",
"slug": "example-voorbeeld-title-2-2"
},
"title": "Voorbeeld Title 2",
"description": "Voorbeeld Description 2"
},
{
"@self": {
"register": "shillinq",
"schema": "example",
"slug": "example-voorbeeld-title-3-3"
},
"title": "Voorbeeld Title 3",
"description": "Voorbeeld Description 3"
},
{
"@self": {
"register": "shillinq",
Expand Down
Loading
Loading