Phase 0: auth-scoped test infrastructure#78
Merged
Conversation
Add dockerized test environment matching production versions, split bootstrap so DB-only tests don't drag in AWS constants, and restore the four bit-rotted unit tests to a green baseline. - tests/docker-compose.test.yml + tests/Dockerfile pin MariaDB 10.5.29 and PHP 8.2 (with mysqli, curl, mbstring) to match the dev server. - tests/bootstrap.php: DB-only, env-var first with constant fallback. - tests/bootstrap-aws.php: AWS constants isolated, opt-in for AWS tests. - phpunit.xml.dist: split into `unit` (default) and `aws` testsuites. - ApiTest: Api::init() was removed; assert construction succeeded and core ModelObject flows work. - DatabaseTest: add setUp that drops test users/DBs before each run (CREATE USER is not idempotent on re-run). - ModelTest::testCreateTable: add missing SELECT keyword in customQuery call. Baseline: 7/7 unit tests pass, 63 assertions. Part of the auth migration initiative described in docs/design/kyte-mcp-and-auth-migration.md (Phase 0). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
First batch of tests locking in the current HMAC-SHA256 auth behavior before the Phase 1 strategy-dispatcher refactor. Documents the three-layer HMAC algorithm and verifies both flow paths (generate then verify, single-request verify) produce identical results. - testSignatureAlgorithmIsThreeLayerHmacSha256: pure algorithm check — hash1 = HMAC(token, secret); hash2 = HMAC(identifier, hash1); signature = HMAC(unix_epoch, hash2). - testGenerateSignatureProducesExpectedValue: Api::generateSignature (flow A step 1) produces the expected signature for known inputs. - testVerifySignatureAcceptsCorrectAndRejectsWrong: correct signature passes, wrong signature throws SessionException. - testParseIdentityStringRejectsExpiredTimestamp: timestamps older than SIGNATURE_TIMEOUT (3600s default) throw "API request has expired". - testParseIdentityStringRejectsMalformedString: identity strings that don't split into exactly 4 parts on '%' throw "Invalid identity string". Uses reflection to reach the private methods (generateSignature, verifySignature, parseIdentityString) without modifying production code. When Phase 1 extracts these into HmacSessionStrategy, the tests will still work if behavior is preserved. Part of docs/design/kyte-mcp-and-auth-migration.md Phase 0. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Extend SignatureTest with six additional characterization tests covering parseIdentityString's branches and the SIGNATURE_TIMEOUT boundary semantics. - testParseIdentityStringAcceptsTimestampAtBoundary: the check is `time() > utcDate + SIGNATURE_TIMEOUT`, so equality must pass. - testParseIdentityStringRejectsTimestampOneSecondPastBoundary: +1s over the window throws SessionException. - testParseIdentityStringRejectsUnknownApiKey: throws a plain \Exception (not SessionException) with "API key not found". - testParseIdentityStringRejectsUnknownAccount: throws \Exception with "Unable to find account". - testParseIdentityStringTreatsUndefinedSessionAsZero: the literal string "undefined" from JS clients is coerced to "0". - testParseIdentityStringWithZeroSessionDoesNotPopulateUser: anonymous (session=="0") leaves $this->user null. Refactor the reflection boilerplate into invokeParseIdentity() helper. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Actually run the tests on every push/PR. Previously the workflow validated composer.json and stopped — the test step was commented out. - Add MariaDB 10.5.29 service container with health check (matches production/dev-server version; GHA waits for healthy before steps). - Set up PHP 8.2 via shivammathur/setup-php with mysqli, curl, mbstring, json extensions. - Inject KYTE_DB_* env vars for bootstrap.php to pick up. - Run vendor/bin/phpunit --testsuite unit (excludes AWS tests, which need real AWS credentials). - Trigger on push to master and any feature/** branch so our Phase 0 branch gets CI coverage. - Add .phpunit.result.cache + clover.xml to .gitignore. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…recated @Depends Three changes, all behavior-preserving, needed to get CI to exit 0 under PHPUnit 11 / PHP 8.2: - src/Core/Api.php: guard model-constant define() calls with defined(). Harmless in production (fresh PHP-FPM process per request), but each `new Api()` in a long-running PHPUnit process was redefining ~50 constants and emitting PHP warnings. PHP's `define()` silently refuses to redefine, so adding the guard matches prior behavior without the warning. - phpunit.xml.dist: migrated to current schema, removed unused <coverage> block. The block referenced clover.xml output but CI sets coverage:none (no driver), which made PHPUnit 11 emit a runner warning. clover.xml is not consumed anywhere — no codecov upload, no artifact, nothing. - tests/FunctionTest.php: replaced @Depends doc-comment with #[Depends] attribute. Doc-comment metadata is deprecated in PHPUnit 11, removed in 12. Prior CI run: 18 passed / 83 assertions, but exit 1 because 51 warnings + 2 deprecations + 1 runner warning. Local post-fix: 18 passed / 83 assertions, OK, no warnings, no deprecations. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Phase 0 of the Kyte MCP / auth migration (see
docs/design/kyte-mcp-and-auth-migration.md). Establishes the auth-scoped test coverage required before Phase 1 refactors the middleware into a strategy dispatcher.unit/awswith explicit file lists, bootstrap split into DB-only (default) and AWS opt-in.tests/SignatureTest.php, 308 lines) covering the three-layer HMAC-SHA256 algorithm,generateSignature(flow A step 1),verifySignature(positive + negative),SIGNATURE_TIMEOUTboundary semantics (inclusive pass, +1s fail), unknown API key / account rejection, malformed identity string, and the"undefined"/"0"session quirks. All reflection-based to invoke private methods without altering source.ApiTest(called removedApi::init()),DatabaseTest(non-idempotentCREATE USER),ModelTest(missingSELECTkeyword), and an@dependsdoc-comment migrated to#[Depends]attribute.unitsuite on push/PR with a MariaDB 10.5.29 service container.Api::loadModelsAndControllers()now guards its ~50define()calls withif (!defined($name)). Behavior-preserving (PHP'sdefine()already silently refuses to redefine; this just suppresses the warning in long-running PHPUnit processes). Flagged in the design doc as a Phase 1 consideration:new Api()has a global-state side effect that should inform how the strategy dispatcher instantiates/reuses Api.18/18 unit tests green, 83 assertions, zero warnings, zero deprecations under PHPUnit 11 / PHP 8.2. CI green on the last push (run 24877617721, 30s).
Explicitly deferred
Not in this PR, revisit at Phase 0.5 or as Phase 1 side-work:
SessionManager-level session validation tests (happy-path, revocation, expired).handleRequestresponse-body parity (kyte_api,kyte_pub,kyte_num,kyte_iden,kyte_app_id,account_id).Neither is a strict blocker for Phase 1 since the strategy-dispatcher refactor doesn't touch
SessionManagersemantics.Post-merge plan
v4.2.0.feature/phase-1-strategy-dispatcheroff the tagged commit.Test plan
v4.2.0via composer, verify Shipyard loads + one API round-tripv4.1.1via composer, verify rollback succeeds🤖 Generated with Claude Code