Skip to content

feat: migrate audit to query-lib schema objects - #206

Closed
abnegate wants to merge 6 commits into
mainfrom
codex/audit-query-lib-publish-20260905
Closed

abnegate wants to merge 6 commits into
mainfrom
codex/audit-query-lib-publish-20260905

Conversation

@abnegate

@abnegate abnegate commented Sep 4, 2026 •

Copy link
Copy Markdown
Member

Summary

Canonical continuation of utopia-php/audit#133 in packages/audit, following the approved move to the monorepo. audit#133 is closed in favour of this.

  • Return typed Attribute and Index schema objects and use Collection for database setup.
  • Adapt ClickHouse schema, DDL and encoding paths to value objects while preserving existing fields, indexes, null handling and tenant behavior.
  • Require the Database dev-feat-query-lib branch from Packagist, with no VCS repository override and no inline alias; declare PDO MySQL and Swoole test extensions.
  • Cover nullable logs, schema defaults and string filtering.

Dependency shape

CLAUDE.md requires packages to depend on siblings through Packagist constraints rather than repository overrides. The branch originally carried a repositories entry pointing at github.com/utopia-php/database.git; that is removed. Packagist already publishes every branch of utopia-php/database, dev-feat-query-lib included, so "utopia-php/database": "dev-feat-query-lib" resolves on its own — and resolves to the branch head rather than to whatever commit an override happened to capture.

utopia-php/validators is ^1.0 here, matching main since #251.

Blocked on

utopia-php/database is still a branch requirement, which is the one thing here that is not a released constraint. It becomes ^8.0 (or whatever utopia-php/database#823 tags as) the moment that PR is merged and tagged, and this PR should not land before then. Nothing else in this branch is waiting on anything.

Verification

Both registry and linked modes passed:

  • Unit: 22 tests, 106 assertions.
  • E2E: 92 tests, 1,023 assertions, including MariaDB and ClickHouse.

Pint, PHPStan, Rector, Composer validation and monorepo validation passed. composer update --dry-run in packages/audit with the override removed resolves utopia-php/database (dev-feat-query-lib 11f8380) plus query 0.6.1, validators 1.0.1 and async 0.1.1, all from Packagist.

No package split, release, tag or merge has been performed.


Do not merge before utopia-php/database 8.0.0 is tagged — the constraint flips to 8.* in one commit first (report 17 release path).

Fixes from the 2026-09-23 review

The audit Query constants now come from the query library (10.11). Utopia\Audit\Query re-declared its 25 legacy
TYPE_* constants (TYPE_EQUAL … TYPE_CURSOR_BEFORE) as string literals that copied Utopia\Query\Method's values.
Each one is now Method::X->value:

  • The values are the same, and the constants are still untyped public constants, so consumers need no change.
  • If utopia-php/query changes a method's value, the constant picks it up instead of keeping the stale string.
  • If a case is renamed or removed, PHPStan fails at the constant, and Query throws the first time it is used.

QueryTest::testConstantMatchesMethod checks that every TYPE_* constant is a Method value.

Commits

  • 7c9c829 refactor(audit): read Query's TYPE_* constants from the Method enum

🤖 Generated with Claude Code

@abnegate

abnegate commented Sep 4, 2026

Copy link
Copy Markdown
Member Author

@greptile-apps review

@abnegate

abnegate commented Sep 6, 2026

Copy link
Copy Markdown
Member Author

@greptileai review the current head 394aa7f. The September 4 request using the older bot handle did not start a review; this uses the currently documented trigger.

@abnegate

abnegate commented Sep 9, 2026

Copy link
Copy Markdown
Member Author

@greptileai review

@greptile-apps

greptile-apps Bot commented Sep 9, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 4/5

The PR is not ready to merge because the audit package still consumes its database sibling through a mutable development-branch constraint, contrary to the repository’s package-boundary requirement.

Fix All in Claude CodeFindings

  1. P2 Mutable Sibling Dependency ▶
Fix with agent prompt
### Issue 1
packages/audit/composer.json:undefined-30
This package replaces the released `utopia-php/database` dependency with the mutable `dev-feat-query-lib` branch and adds a direct VCS repository override at lines 38–41. The repository requires independent packages to consume siblings through Packagist constraints. This requirement must be satisfied before merging so installs use the supported distribution boundary rather than mutable branch contents.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Summary

The PR migrates the audit adapters from array-shaped schema definitions to typed database Attribute, Index, and Collection objects while retaining database and ClickHouse behavior.

  • Updates ClickHouse schema generation, insert encoding, and column/index handling for typed objects.
  • Updates database setup to pass a typed collection definition.
  • Adds behavioral coverage for nullable fields, full-length user identifiers, defaults, and string filtering.
  • Removes the direct VCS repository override added earlier in the PR.

Reviews (5) · Last reviewed commit: "chore(audit): take the database branch f..."

Comment thread packages/audit/tests/Audit/Adapter/DatabaseTest.php Outdated
Comment thread packages/audit/composer.json
The schema assertions pinned attribute counts, array positions, column
types, sizes, filters, index types and index column ordering straight off
the adapter's getAttributes()/getIndexes(). That mirrors the source rather
than testing it: the repository requires observable behaviour, and these
lines only ever compared the schema definition against a second copy of
itself.

Every deleted property is already covered through the public API, proven
by breaking each one and watching a behavioural test go red: dropping the
json filter on data, dropping the datetime filter on time, making
idx_userId_event unique and making userId required each fail the existing
write/read tests. Index column ordering is the one property with no
observable behaviour at all -- swapping it reaches the real DDL and every
test still passes -- so no assertion can guard it.

userId's size was the only property not otherwise reachable, so it is
replaced rather than dropped: testUserIdAcceptsFullKeyLength writes a
key-length user id and reads it back, which fails once the column shrinks.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@abnegate

abnegate commented Sep 9, 2026

Copy link
Copy Markdown
Member Author

@greptileai review

@abnegate
abnegate force-pushed the codex/audit-query-lib-publish-20260905 branch from d7bd655 to 4e53dd5 Compare September 9, 2026 10:14
@abnegate

abnegate commented Sep 9, 2026

Copy link
Copy Markdown
Member Author

Both findings addressed at 4e53dd58.

Finding 1 — tests mirror schema internals: fixed.

DatabaseTest::testSchemaValueObjectsAndNullableLog and ClickHouseTest::testPremiumGeoAttributesAreOptionalStrings are gone. Before deleting anything I broke each property in the schema and checked a behavioural test actually goes red, so the coverage is proven and not assumed:

schema change outcome
drop filters: ['json'] on data 17/17 DatabaseTest red — Attribute "data" has invalid type
drop filters: ['datetime'] on time testLogByBatch red
idx_userId_event Index::key → Index::unique 17/17 red (createLogs() writes duplicate userId+event pairs)
userId required: false → true 17/17 red
userId size 255 → 128 testUserIdAcceptsFullKeyLength red
idx_userId_event attributes ['userId','event'] → ['event','userId'] green

That last row is the interesting one. The swap reaches the real DDL (KEY idx_userId_event (event, userId)) and all 16 remaining tests still pass, because index column order is a query-planner concern with no behaviour observable through the audit API. No test can ever guard it — which is exactly why asserting it only compared the schema against a second copy of itself.

One property was not otherwise reachable, so it is replaced rather than dropped: userId's size is now covered by testUserIdAcceptsFullKeyLength, which writes a key-length user id and reads it back.

The ClickHouse geo flags are fully subsumed by the existing testPremiumGeoRoundTrip, which writes all nine geo fields and asserts each round-trips unchanged; required is covered by every test's setUp(), which writes logs carrying no geo fields at all.

Finding 2 — ext-swoole: this one is a false positive, and I've left the requirement in place.

The premise is right (nothing under packages/audit mentions Swoole — grep -rniE 'swoole|Coroutine|WaitGroup|\bgo\(' over src/, tests/ and the README returns nothing) but the requirement is transitive, not local. utopia-php/database@dev-feat-query-lib calls it unguarded:

// vendor/utopia-php/database/src/Database/Database.php:1442
private function getEventContext(): int
{
    $context = Coroutine::getCid();

getEventContext() backs silent() / areEventsSilenced(), which deleteDocuments() uses — the path Audit::cleanup() takes, which every test hits in setUp(). Note line 2848 in the same file does guard with extension_loaded('swoole'); line 1442 does not, and utopia-php/database declares no ext-swoole of its own.

I pushed the removal first and CI proved it: test (audit) went to 17 errors, Class "Swoole\Coroutine" not found, and it reproduces locally with the extension unloaded. Dropping the requirement doesn't make the package installable without Swoole, it just converts a clear resolution-time error into 17 runtime fatals — so the declaration stays, per the house preference for declaring real ext-* requirements over --ignore-platform-reqs.

The real fix belongs upstream (guard line 1442 like 2848, or declare ext-swoole in utopia-php/database); tracking that separately rather than in this PR.

Verified at 4e53dd58: unit OK (22 tests, 106 assertions), e2e OK (92 tests, 956 assertions), and bin/monorepo check audit — pint, phpstan level 5, rector — all pass.

@abnegate

abnegate commented Sep 9, 2026

Copy link
Copy Markdown
Member Author

@greptileai review

Picks up the Validators ^1.0 requirement from main so packages/audit no
longer drifts from the sibling constraint.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Comment thread packages/audit/composer.json
Jake Barnby and others added 2 commits September 22, 2026 17:05
…ride

CLAUDE.md requires packages to depend on siblings through Packagist
constraints. Packagist already serves every branch of utopia-php/database,
including feat-query-lib, so the repository override bought nothing and
pinned resolution to whatever commit the last lock captured. Without it
composer resolves the branch head directly.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Utopia\Audit\Query re-declared its 25 legacy TYPE_* method names as
string literals, duplicating values that utopia-php/query's Method enum
owns (review finding 10.11). They match today, but nothing tied the two
together: if query changed a case's value, the constants would keep the
old string with no error anywhere. A query built from one would then
throw in Method::from(), and a comparison with getMethod()->value would
quietly turn false.

Each constant is now Method::X->value, so a changed value carries over
on its own, and a renamed or removed case fails PHPStan at the constant
and throws on the first Query instantiation. The values and the public
API are unchanged; the constants stay untyped, so a subclass that
redeclares one still compiles.

QueryTest gains a parity test asserting that every TYPE_* constant is a
Method value. It passes before and after this change because the values
match; it fails as soon as a literal falls out of step with the enum.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@walter-o-brien

walter-o-brien Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

🔍 OpenCodeReview found 2 issue(s) in this PR.

  • ✅ Successfully posted inline: 2 comment(s)

Comment thread packages/audit/composer.json
Comment thread packages/audit/src/Audit/Adapter/SQL.php
@ChiragAgg5k

Copy link
Copy Markdown
Member

Audit now lives in packages/audit in appwrite/appwrite (appwrite/appwrite#13955), and this copy is being retired. @abnegate, please re-open this against packages/audit there if you still want it.

abnegate added a commit to appwrite/appwrite that referenced this pull request Sep 29, 2026
utopia-php/monorepo#206 prepared audit 5.0.0 for utopia-php/database 8:
the adapters read attributes and indexes as typed Attribute and Index
models, and the legacy TYPE_* constants come from Method. Main absorbed
audit into packages/audit (#13955) and the monorepo closed #206 in
favour of a change here, so this applies #206's candidate (mirror head
f8422f9cbf) to the package, line for line, with its tests. Main's
utopia-php/client transport stays; the train only touched the schema
code around it. getAttribute() now declares ?Attribute, so its
not-found branch returns null explicitly, and two baseline entries go
with the errors the port removes. The package requires database ^8.0
with dev stability until 8.0.0 is tagged, because bin/monorepo check
and test resolve it from Packagist.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants