From b11326f18cb5f31c33afec5f307cae5fc5074f27 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Jan 2026 21:50:45 +0000 Subject: [PATCH 1/9] chore(deps-dev): bump org.assertj:assertj-core Bumps the maven group with 1 update in the / directory: [org.assertj:assertj-core](https://github.com/assertj/assertj). Updates `org.assertj:assertj-core` from 3.24.2 to 3.27.7 - [Release notes](https://github.com/assertj/assertj/releases) - [Commits](https://github.com/assertj/assertj/compare/assertj-build-3.24.2...assertj-build-3.27.7) --- updated-dependencies: - dependency-name: org.assertj:assertj-core dependency-version: 3.27.7 dependency-type: direct:development dependency-group: maven ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 93c53c8..6667f41 100644 --- a/pom.xml +++ b/pom.xml @@ -36,7 +36,7 @@ org.assertj assertj-core - 3.24.2 + 3.27.7 test -- 2.54.0 From e7d4b4d672cc47312293d013dd91e68ea57ca1d2 Mon Sep 17 00:00:00 2001 From: James Maes Date: Thu, 21 May 2026 17:14:34 -0500 Subject: [PATCH 2/9] chore: add CODEOWNERS pointing to sole maintainer Architecture audit pass 2026-05-21. Minimal CODEOWNERS file making the implicit ownership explicit. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/CODEOWNERS | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..e7d84f9 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @KofTwentyTwo -- 2.54.0 From a20a38255e0c67632bca88a9006ddab4ca5ab281 Mon Sep 17 00:00:00 2001 From: James Maes Date: Sun, 12 Jul 2026 05:31:23 -0500 Subject: [PATCH 3/9] docs: add CLAUDE.md pointer to QQQ knowledge-base dossier + hub Co-Authored-By: Claude Opus 4.8 --- CLAUDE.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..4ab3610 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,13 @@ +# qbit-template-extension + +GitHub template repository for scaffolding QQQ "Extension QBits" (infrastructure-level plugins: table customizers, auth, audit, action wrappers). Not a shipping library — consumers click "Use this template" and rename the `com.kingsrook.qbits.example` package. + +## Knowledge base + +Reviewed dossiers for this repo and the wider QQQ platform live in the second-brain vault: + +- Hub / entry point: `R:/Git.Local/KofTwentyTwo/second-brain/knowledge/qqq/qqq-hub.md` +- This repo's dossier: `R:/Git.Local/KofTwentyTwo/second-brain/knowledge/qqq/repos/qbit-template-extension.md` +- QBit mechanics refresher: `R:/Git.Local/KofTwentyTwo/second-brain/knowledge/qqq/architecture/metadata-model.md` + +Reviewed at commit `e7d4b4d672cc` (branch `main`, 2026-05-21). Known drift as of that review: no `qbit-build-parent` parent pom (org convention), qqq pinned at 0.35.0 on main (0.40.0-SNAPSHOT on develop), README still claims AGPL-3.0 while LICENSE/NOTICE are Apache-2.0, and README references `scripts/customize_template.py` / `actions/ExampleActionCustomizer.java` which do not exist. See the dossier's "Maturity & risks" and "v4.0 impact" sections before modifying the scaffold. -- 2.54.0 From 92f2ec557bd9c908127d289172b00cd205e6d802 Mon Sep 17 00:00:00 2001 From: James Maes Date: Thu, 24 Sep 2026 13:32:16 -0500 Subject: [PATCH 4/9] feat(release): migrate extension template to QQQ 4.0 (#4) * fix(template): prepare extension scaffold for QQQ 4.0 * fix(ci): avoid interactive package restart prompts * docs: align guides and examples with QQQ 4.0 * docs(release): finalize QQQ 4.0 template instructions Refs QRun-IO/qqq#631. --- .circleci/config.yml | 14 ++++++++- CLAUDE.md | 4 +++ README.md | 14 +++------ docs/00-getting-started.md | 48 +++++++++++------------------- docs/01-extension-patterns.md | 56 +++++------------------------------ pom.xml | 2 +- 6 files changed, 46 insertions(+), 92 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 8828026..010cd62 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -3,7 +3,19 @@ version: 2.1 orbs: qqq-orb: kingsrook/qqq-orb@0.5.0 +commands: + configure-package-install: + steps: + - run: + name: Keep package installation unattended + command: | + # These build machines are discarded after the job. + sudo install -d /etc/needrestart/conf.d + printf '%s\n' '$nrconf{restart} = "l";' | sudo tee /etc/needrestart/conf.d/99-qqq-ci.conf >/dev/null + workflows: build: jobs: - - qqq-orb/mvn_test + - qqq-orb/mvn_test_only: + pre-steps: + - configure-package-install diff --git a/CLAUDE.md b/CLAUDE.md index 4ab3610..e9917d3 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -2,6 +2,10 @@ GitHub template repository for scaffolding QQQ "Extension QBits" (infrastructure-level plugins: table customizers, auth, audit, action wrappers). Not a shipping library — consumers click "Use this template" and rename the `com.kingsrook.qbits.example` package. +## QQQ 4.0 baseline — 2026-09-24 + +The historical review below predates the 4.0 migration. This template targets Java 21 and the public QQQ 4.0.0 release from Maven Central. The corrected APIs, license references and actual template commands are in README.md and docs/00-getting-started.md. Preserve the documented multi-instance and scaffold limitations. + ## Knowledge base Reviewed dossiers for this repo and the wider QQQ platform live in the second-brain vault: diff --git a/README.md b/README.md index 15ea3b1..4b03f15 100644 --- a/README.md +++ b/README.md @@ -13,11 +13,7 @@ Extension QBits extend or enhance how QQQ operates at the infrastructure/framewo ## Quick Start -1. Click "Use this template" to create your QBit -2. Run `scripts/customize_template.py` to rename the example -3. Implement your extension logic -4. Add tests -5. Publish to Maven repository +Requires **Java 21**, **Maven 3.8+**, and QQQ **4.0.0**. Create your repository, customize its Maven coordinates and Java package/classes, implement the table customizer, then run `mvn clean verify`. See [Getting Started](docs/00-getting-started.md). ## Structure @@ -25,10 +21,8 @@ Extension QBits extend or enhance how QQQ operates at the infrastructure/framewo src/main/java/com/kingsrook/qbits/example/ ├── ExampleExtensionQBitConfig.java # Configuration ├── ExampleExtensionQBitProducer.java # Entry point -├── customizers/ -│ └── ExampleTableCustomizer.java # Table customization -└── actions/ - └── ExampleActionCustomizer.java # Action handling +└── customizers/ + └── ExampleTableCustomizer.java # Table customization ``` ## Key Characteristics @@ -45,4 +39,4 @@ src/main/java/com/kingsrook/qbits/example/ ## License -AGPL-3.0 - See [LICENSE](LICENSE) +See [LICENSE](LICENSE) and [NOTICE](NOTICE). diff --git a/docs/00-getting-started.md b/docs/00-getting-started.md index f019f1e..fe1538c 100644 --- a/docs/00-getting-started.md +++ b/docs/00-getting-started.md @@ -1,42 +1,28 @@ # Getting Started -## Prerequisites +Targets Java 21, Maven 3.8 or later, and QQQ 4.0.0. Maven resolves the framework dependencies from Maven Central. -- Java 17+ -- Maven 3.8+ -- QQQ 0.23.0+ +1. Choose **Use this template** on GitHub, then clone the repository you created. +2. In `pom.xml`, set your own `groupId`, `artifactId`, name, description, and version. +3. Use your IDE's package refactoring to rename `com.kingsrook.qbits.example` throughout `src/`. Rename the `Example*` classes and update their imports and references with the IDE's rename refactoring. +4. Update the QBit producer's `GROUP_ID`, `ARTIFACT_ID`, and `VERSION` constants to match your project. Give the metadata names their own stable names before combining the QBit with other examples. +5. Build the generated project: -## Creating Your Extension QBit - -1. Click "Use this template" on GitHub -2. Clone your new repository -3. Run the customization script: - ```bash - python scripts/customize_template.py - ``` -4. Enter your QBit name when prompted - -## Project Structure - -``` -src/main/java/com/kingsrook/qbits/yourextension/ -├── YourExtensionQBitConfig.java -├── YourExtensionQBitProducer.java -├── customizers/ -└── actions/ +```bash +mvn clean verify ``` -## Using Your QBit +The repository provides example Java sources; customization uses normal package/class refactoring. Keep example coordinates unpublished. After customizing, add tests for your QBit's behavior before setting up its publishing workflow. + +## Register with a host application + +The following uses the original example names; substitute the names chosen above: ```java -new YourExtensionQBitProducer() - .withConfig(new YourExtensionQBitConfig() +new ExampleExtensionQBitProducer() + .withConfig(new ExampleExtensionQBitConfig() .withTargetTableName("order")) - .produce(qInstance, "myExtension"); + .produce(qInstance, "my-extension"); ``` -## Next Steps - -- Read [Extension Patterns](01-extension-patterns.md) -- Implement your customization logic -- Add tests +Register the target table before producing the extension, then implement its customizer. See [Extension Patterns](01-extension-patterns.md). diff --git a/docs/01-extension-patterns.md b/docs/01-extension-patterns.md index 5c90fdc..55ccff7 100644 --- a/docs/01-extension-patterns.md +++ b/docs/01-extension-patterns.md @@ -1,58 +1,16 @@ # Extension Patterns -## Table Customizers - -Add behavior to existing tables: +[ExampleExtensionQBitProducer](../src/main/java/com/kingsrook/qbits/example/ExampleExtensionQBitProducer.java) registers the QBit identity and calls `applyTableCustomizations` for the configured target. That method is the extension point: look up the table, validate that it exists, and call your customized [ExampleTableCustomizer](../src/main/java/com/kingsrook/qbits/example/customizers/ExampleTableCustomizer.java). ```java -public class AuditTableCustomizer +QTableMetaData table = qInstance.getTable(tableName); +if(table == null) { - public void customize(QTableMetaData table) - { - table.withField(new QFieldMetaData("createdAt", QFieldType.DATE_TIME)); - table.withField(new QFieldMetaData("modifiedAt", QFieldType.DATE_TIME)); - - table.withCustomizer( - TableCustomizers.PRE_INSERT_RECORD, - new QCodeReference(AuditPreInsert.class)); - } + throw new QException("Target table not found: " + tableName); } +new ExampleTableCustomizer().customize(table); ``` -## Action Customizers +When implementing this method, add `throws QException` to its declaration. Run the config's `validate(QInstance, List)` before registering metadata, and report validation errors rather than silently ignoring a missing target. The uncustomized template contains placeholders for this behavior. -Wrap actions with additional behavior: - -```java -public class LoggingActionWrapper implements PreInsertRecordInterface -{ - @Override - public void preInsertRecord(InsertInput input, QRecord record) throws QException - { - LOG.info("Inserting record", logPair("table", input.getTableName())); - } -} -``` - -## Config Validation - -Validate that required components exist: - -```java -@Override -public void validate(QInstance qInstance, List errors) -{ - if(qInstance.getTable(targetTableName) == null) - { - errors.add("Target table required: " + targetTableName); - } -} -``` - -## When to Use Extension QBits - -- Adding audit logging to tables -- Implementing authentication/authorization -- Adding encryption to fields -- Custom validation rules -- Performance monitoring +For record hooks, use QQQ's existing table customizer interfaces or `AbstractPreInsertCustomizer`. Its `apply(List)` method returns the records for the next stage; register the customizer through the table's `TableCustomizers.PRE_INSERT_RECORD` role. Check the actual QQQ interface before adding another hook. Add tests proving that the intended table changes and invalid configurations are handled. diff --git a/pom.xml b/pom.xml index 93c53c8..67c7f41 100644 --- a/pom.xml +++ b/pom.xml @@ -17,7 +17,7 @@ 21 21 UTF-8 - 0.35.0 + 4.0.0 -- 2.54.0 From b1d5938f56e66e9639ba73407492f8066c4cd0a2 Mon Sep 17 00:00:00 2001 From: James Maes Date: Tue, 20 Oct 2026 07:22:01 -0500 Subject: [PATCH 5/9] ci: adopt central QQQ orb 0.7.4 Co-Authored-By: Codex --- .circleci/config.yml | 29 +++++++++++------------------ .qqq-ci.yml | 16 ++++++++++++++++ 2 files changed, 27 insertions(+), 18 deletions(-) create mode 100644 .qqq-ci.yml diff --git a/.circleci/config.yml b/.circleci/config.yml index 010cd62..f8102d3 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,21 +1,14 @@ version: 2.1 - +setup: true orbs: - qqq-orb: kingsrook/qqq-orb@0.5.0 - -commands: - configure-package-install: - steps: - - run: - name: Keep package installation unattended - command: | - # These build machines are discarded after the job. - sudo install -d /etc/needrestart/conf.d - printf '%s\n' '$nrconf{restart} = "l";' | sudo tee /etc/needrestart/conf.d/99-qqq-ci.conf >/dev/null - + qqq-orb: kingsrook/qqq-orb@0.7.4 workflows: - build: - jobs: - - qqq-orb/mvn_test_only: - pre-steps: - - configure-package-install + setup: + jobs: + - qqq-orb/generate_pipeline: + orb_version: 0.7.4 + filters: + branches: + ignore: automation/qbit-rc-pending + tags: + ignore: /.*/ diff --git a/.qqq-ci.yml b/.qqq-ci.yml new file mode 100644 index 0000000..dc27824 --- /dev/null +++ b/.qqq-ci.yml @@ -0,0 +1,16 @@ +profile: qbit +orb_version: 0.7.4 +default_branch: main +java_version: '21' +browsers: true +api_checks: false +docs_only: false +release_on_main: false +release_tag_policy: none +test_branch_policy: all +publish: + snapshot: false + release_candidate: false + release: false + asciidoc: false +release_completion: false -- 2.54.0 From 530b41959f205d351ec3bd079ae6d8e7f8356da3 Mon Sep 17 00:00:00 2001 From: James Maes Date: Wed, 21 Oct 2026 00:55:58 -0500 Subject: [PATCH 6/9] ci: adopt shared orb 0.7.11 (#6) Co-authored-by: Codex --- .circleci/config.yml | 4 ++-- .qqq-ci.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index f8102d3..ff93256 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,12 +1,12 @@ version: 2.1 setup: true orbs: - qqq-orb: kingsrook/qqq-orb@0.7.4 + qqq-orb: kingsrook/qqq-orb@0.7.11 workflows: setup: jobs: - qqq-orb/generate_pipeline: - orb_version: 0.7.4 + orb_version: 0.7.11 filters: branches: ignore: automation/qbit-rc-pending diff --git a/.qqq-ci.yml b/.qqq-ci.yml index dc27824..8e2829f 100644 --- a/.qqq-ci.yml +++ b/.qqq-ci.yml @@ -1,5 +1,5 @@ profile: qbit -orb_version: 0.7.4 +orb_version: 0.7.11 default_branch: main java_version: '21' browsers: true -- 2.54.0 From 674bbdf8c10ce47831a7fcc9a91dba7d159b5941 Mon Sep 17 00:00:00 2001 From: James Maes Date: Wed, 21 Oct 2026 08:51:36 -0500 Subject: [PATCH 7/9] ci: adopt central orb 0.7.12 and stable gates (#7) Co-authored-by: Codex --- .circleci/config.yml | 4 ++-- .qqq-ci.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index ff93256..8b8bfbd 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,12 +1,12 @@ version: 2.1 setup: true orbs: - qqq-orb: kingsrook/qqq-orb@0.7.11 + qqq-orb: kingsrook/qqq-orb@0.7.12 workflows: setup: jobs: - qqq-orb/generate_pipeline: - orb_version: 0.7.11 + orb_version: 0.7.12 filters: branches: ignore: automation/qbit-rc-pending diff --git a/.qqq-ci.yml b/.qqq-ci.yml index 8e2829f..7028d97 100644 --- a/.qqq-ci.yml +++ b/.qqq-ci.yml @@ -1,5 +1,5 @@ profile: qbit -orb_version: 0.7.11 +orb_version: 0.7.12 default_branch: main java_version: '21' browsers: true -- 2.54.0 From 9e83211c4e54a73cc882ec2846e7c96da8a13ea1 Mon Sep 17 00:00:00 2001 From: James Maes Date: Wed, 21 Oct 2026 16:34:57 -0500 Subject: [PATCH 8/9] ci: adopt managed orb 0.8 patch track (#8) Co-authored-by: Codex --- .circleci/config.yml | 4 ++-- .qqq-ci.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 8b8bfbd..32df77b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,12 +1,12 @@ version: 2.1 setup: true orbs: - qqq-orb: kingsrook/qqq-orb@0.7.12 + qqq-orb: kingsrook/qqq-orb@0.8 workflows: setup: jobs: - qqq-orb/generate_pipeline: - orb_version: 0.7.12 + orb_version: '0.8' filters: branches: ignore: automation/qbit-rc-pending diff --git a/.qqq-ci.yml b/.qqq-ci.yml index 7028d97..d65dd23 100644 --- a/.qqq-ci.yml +++ b/.qqq-ci.yml @@ -1,5 +1,5 @@ profile: qbit -orb_version: 0.7.12 +orb_version: '0.8' default_branch: main java_version: '21' browsers: true -- 2.54.0 From a5873701d70cbeb5df943c77662edac5b5d3d13d Mon Sep 17 00:00:00 2001 From: James Maes Date: Wed, 21 Oct 2026 18:31:18 -0500 Subject: [PATCH 9/9] ci: use central orb pipeline on develop Co-Authored-By: Codex --- .circleci/config.yml | 17 +++++++++++------ .qqq-ci.yml | 16 ++++++++++++++++ 2 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 .qqq-ci.yml diff --git a/.circleci/config.yml b/.circleci/config.yml index 8828026..32df77b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,9 +1,14 @@ version: 2.1 - +setup: true orbs: - qqq-orb: kingsrook/qqq-orb@0.5.0 - + qqq-orb: kingsrook/qqq-orb@0.8 workflows: - build: - jobs: - - qqq-orb/mvn_test + setup: + jobs: + - qqq-orb/generate_pipeline: + orb_version: '0.8' + filters: + branches: + ignore: automation/qbit-rc-pending + tags: + ignore: /.*/ diff --git a/.qqq-ci.yml b/.qqq-ci.yml new file mode 100644 index 0000000..d65dd23 --- /dev/null +++ b/.qqq-ci.yml @@ -0,0 +1,16 @@ +profile: qbit +orb_version: '0.8' +default_branch: main +java_version: '21' +browsers: true +api_checks: false +docs_only: false +release_on_main: false +release_tag_policy: none +test_branch_policy: all +publish: + snapshot: false + release_candidate: false + release: false + asciidoc: false +release_completion: false -- 2.54.0