Skip to content

Conversation

@withinboredom
Copy link
Member

@withinboredom withinboredom commented Jul 26, 2025

Summary by CodeRabbit

  • Chores
    • Removed Docker Hub login steps from build workflows.
    • Upgraded Go module to version 1.24 and updated dependencies.
    • Increased PHP version requirement to 8.4 and upgraded PHP packages.
    • Updated Golang and PHP base images in Dockerfile.
    • Enhanced IDE configurations and cleaned redundant entries.
    • Refined time unit references and improved multibyte string trimming.
    • Removed CPU profiling and request logger options.
    • Reformatted code for multiline style and trailing commas.
    • Updated entity classes to extend base record with protected setters.
    • Introduced factory functions for entity and orchestration instance creation.
    • Replaced direct class instantiations with factory function calls across code and tests.
    • Improved code readability with formatting and style adjustments.
    • Replaced internal state ID and kind references to use a unified package.
    • Added authorization context injection in API request headers.
    • Simplified and corrected authorization and resource management code.
    • Added Docker build tag "nowatcher" for CLI build.
  • New Features
    • Added support for proxy code generation of public properties with getter/setter hooks.
    • Enhanced proxy generation to support hook behaviors modifying method implementations.
    • Added property get/set support via special syntax in entity history execution.
    • Introduced custom serialization and deserialization for record objects.
    • Added new API endpoints and client methods to share ownership and grant access to resources by user or role.
    • Extended CLI user creation command with roles and claims options.
    • Added authorization context classes and methods for sharing ownership and permission grants.
    • Added functions to instantiate authorization share types (Owner, Role, User) with allowed operations.
    • Extended durable client and remote clients with ownership sharing and permission management methods.
    • Added interface methods for entity and orchestration access control and ownership sharing.
  • Bug Fixes
    • Fixed typo in log message: "Unkown endpoint" → "Unknown endpoint".
  • Tests
    • Extended test interfaces with new public properties and updated proxy tests to use snapshots.
    • Added comprehensive unit tests for event description covering diverse scenarios and serialization.
    • Added serialization/deserialization tests for entity and orchestration record classes.

Signed-off-by: Rob Landers <landers.robert@gmail.com>
@coderabbitai
Copy link

coderabbitai bot commented Jul 26, 2025

Walkthrough

The workflow file .github/workflows/build-cli.yaml was updated to remove Docker Hub login steps and delete the build-linux and build-osx jobs, while retaining GitHub Container Registry login in the build-docker job. The Go module version in cli/go.mod was upgraded from 1.23 to 1.24.5 with multiple dependency updates. Several IDE configuration files under .idea/ were modified to adjust test source folders, excluded directories, and PHP include paths. The Dockerfile base images for Golang and PHP were updated to newer patch versions. CPU profiling code was removed from cli/cli.go and logger options were removed from FrankenPHP request creation in cli/glue/glue.go and cli/lib/api.go. The PHP version requirement in composer.json was raised from 8.3 to 8.4, and multiple package versions were updated. Various source files updated time unit imports from TimeUnit to Unit and replaced string trimming functions with multibyte-safe variants. Duplicate XML suite configurations were removed from .idea/phpspec.xml. Minor whitespace cleanup was done in cli/Makefile. Proxy classes (ClientProxy, Generator, OrchestratorProxy, SpyProxy) were refactored to add an optional $isHook parameter to key methods, enabling hook-specific code generation for methods and properties. Test interfaces were extended with a new public property prop. No public API signature changes except for nullable string type hints in src/Events/TaskFailed.php. Additionally, src/State/EntityHistory.php was enhanced to support direct property get/set operations via a new "::" syntax in the execute method. New factory functions EntityId() and OrchestrationInstance() were introduced and used throughout the codebase to replace direct instantiation with new. A new Exporter class was added to customize serialization/deserialization of Record objects. A comprehensive unit test for EventDescription was added, and new tests for serialization of EntityId and OrchestrationInstance were included. Ownership sharing functionality was added to RemoteEntityClient, DurableClient, and EntityClientInterface. The cli/auth/keys.go was extended to support additional JWT claims and user retrieval from context. A new SpyException class was introduced.

Changes

Cohort / File(s) Change Summary
CI Workflow
.github/workflows/build-cli.yaml
Removed Docker Hub login steps and deleted build-linux and build-osx jobs; retained GitHub Container Registry login.
Go Module and Dockerfile
cli/go.mod, Dockerfile
Upgraded Go version to 1.24.5; updated direct and indirect dependencies; updated Golang and PHP base images and Alpine packages.
IDE Configuration
.idea/codeception.xml, .idea/durable-php.iml, .idea/php.xml, .idea/phpspec.xml
Deleted Codeception config; updated test source folders and excluded vendor directories; adjusted PHP include paths and language level; removed duplicate PhpSpecSuiteConfiguration elements.
CLI and FrankenPHP
cli/cli.go, cli/glue/glue.go, cli/lib/api.go
Removed CPU profiling code and imports; removed logger option from FrankenPHP request creation; replaced glue ID types with ids package equivalents; fixed error message quoting and typo.
Composer and PHP Version
composer.json
Raised PHP version requirement from >=8.3 to >=8.4; updated package versions; added new package dependency and autoload files.
Time Unit and String Functions Updates
src/Events/EventQueue.php, src/Glue/glue.php, src/RemoteOrchestrationClient.php, tests/ClientTestCli.php, src/RemoteEntityClient.php
Replaced TimeUnit imports with Unit; updated usage accordingly; replaced trim and rtrim with multibyte-safe mb_trim and mb_rtrim.
Proxy Classes Refactor
src/Proxy/ClientProxy.php, src/Proxy/Generator.php, src/Proxy/OrchestratorProxy.php, src/Proxy/SpyProxy.php
Added optional $isHook parameter to pureMethod and impureCall; updated method bodies for hook-specific behavior; improved imports and formatting; added support for public properties with getter/setter hooks in Generator.
Entity and Orchestration ID Refactor
src/State/EntityId.php, src/State/OrchestrationInstance.php, src/State/Ids/StateId.php, src/functions.php
Converted classes to extend Record base class; replaced constructors with protected-set properties; added static factory methods; introduced global factory functions EntityId() and OrchestrationInstance() for instantiation instead of new.
Code Style and Formatting
src/State/EntityHistory.php, src/OrchestrationContext.php, tests/Unit/OrchestrationHistoryTest.php, tests/Unit/EntityHistoryTest.php, tests/Unit/LockIntegrationTest.php, tests/Unit/ActivityHistoryTest.php, tests/PerformanceTests/*, tests/Feature/*, tests/Pest.php, cli/Makefile
Reformatted code to multiline style with trailing commas; adjusted import statements; replaced direct instantiations with factory function calls; minor whitespace cleanup; updated test interfaces with new public property prop; replaced explicit proxy code checks with snapshot assertions; no logic changes.
Bugfixes and Minor Corrections
cli/lib/api.go
Corrected typo in log message ("Unkown" to "Unknown"); fixed error message quoting in HTTP response.
Serialization Enhancements
src/State/Exporter.php, src/State/Serializer.php, tests/Unit/RecordTest.php
Added Exporter class to handle serialization/deserialization of Record objects; updated serializer to use this exporter; added tests for serialization of EntityId and OrchestrationInstance.
EventDescription Improvements and Tests
src/Events/EventDescription.php, tests/Unit/EventDescriptionTest.php
Added null safety and improved serialization logic; added comprehensive unit tests covering various event scenarios and serialization round-trips.
EntityHistory Enhancements
src/State/EntityHistory.php
Added support for direct property get/set operations via "::" syntax in execute method; reformatted code for multiline style with trailing commas.
Auth and User Claims
cli/auth/keys.go
Added function to retrieve user from context; extended CreateUser to accept additional claims and adjust JWT claims accordingly.
RemoteEntityClient Ownership Sharing
src/RemoteEntityClient.php
Added shareEntityOwnership, grantEntityAccessToUser, grantEntityAccessToRole, revokeEntityAccessToUser, revokeEntityAccessToRole methods; adjusted signal method to catch specific exception; replaced string trimming with multibyte-safe function.
RemoteOrchestrationClient Ownership Sharing
src/RemoteOrchestrationClient.php
Added shareOrchestrationOwnership, grantOrchestrationAccessToUser, grantOrchestrationAccessToRole, revokeOrchestrationAccessToUser, revokeOrchestrationAccessToRole methods; replaced string trimming and object construction style.
DurableClient Ownership Sharing
src/DurableClient.php
Added ownership sharing and access control methods for entities and orchestrations delegating to internal clients.
EntityClientInterface Ownership Sharing
src/EntityClientInterface.php
Added method signatures for ownership sharing and access control for entities.
OrchestrationClientInterface Ownership Sharing
src/OrchestrationClientInterface.php
Added method signatures for ownership sharing and access control for orchestrations; updated method signatures and imports.
Auth Resource Manager Enhancements
cli/auth/resourceManager.go
Changed DiscoverResource parameter type from *glue.StateId to *ids.StateId; added ToAuthContext method to generate JSON authorization context from resource owners and shares.
Auth Context Classes and Functions
src/Contexts/AuthContext.php, src/Contexts/AuthContext/Share.php, src/Contexts/AuthContext/Share/Owner.php, src/Contexts/AuthContext/Share/Role.php, src/Contexts/AuthContext/Share/User.php, src/Contexts/AuthContext/functions.php
Added AuthContext class representing authorization context with owners and shares; added abstract Share class with polymorphic subclasses Owner, Role, and User; added factory functions for these share types.
EntityContext Ownership Methods
src/EntityContext.php
Added methods to share ownership, give ownership, grant user/role permissions, and revoke user/role permissions, firing corresponding events.
EntityContextInterface Ownership Methods
src/EntityContextInterface.php
Added interface method signatures for ownership sharing, permission granting, revoking, and ownership transfer.
Glue and API Authorization Updates
cli/glue/glue.go, cli/lib/api.go, cli/auth/resource.go, cli/glue/response_writer.go, cli/glue/state.go, cli/lib/billing.go, cli/lib/consumer.go, cli/lib/indexer.go, cli/lib/locks.go
Replaced all glue package references for IDs and kinds with ids package equivalents; updated function signatures and calls accordingly; enhanced API handlers to support sharing and granting/revoking permissions; added authorization context injection in API request headers.
SpyException Addition
src/Proxy/SpyException.php
Added new exception class SpyException extending DomainException.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

Possibly related PRs

  • update time library and misc fixes #74: Modifies the build workflow by removing specific performance test steps and updates Go version from 1.22 to 1.23; related to .github/workflows/build-cli.yaml and cli/go.mod changes but with different specifics.

Poem

🐇
We’ve trimmed the logs, and trimmed the code,
With multibyte care down every road.
No Docker Hub secrets left to hide,
Just GitHub tokens by our side.
Go’s version hops up, dependencies too,
Cleaner configs, fresh and new!
Proxy hooks now dance with flair—
A rabbit’s cheer for builds that dare!
🥕✨

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch withinboredom-patch-1

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Signed-off-by: Robert Landers <landers.robert@gmail.com>
Signed-off-by: Robert Landers <landers.robert@gmail.com>
Signed-off-by: Robert Landers <landers.robert@gmail.com>
Signed-off-by: Robert Landers <landers.robert@gmail.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
cli/Makefile (1)

1-18: LGTM! Clean whitespace removal.

The trailing whitespace cleanup improves code hygiene without affecting functionality.

Consider adding phony targets for better Makefile practices:

+.PHONY: all clean test
+
 TARGET := dphp-linux-*
cli/cli.go (1)

93-112: Remove commented code instead of leaving it in place.

The CPU profiling functionality has been disabled by commenting out the code. For cleaner code maintenance, consider fully removing the commented lines instead of leaving them in place.

-		//profile, err := os.CreateTemp("", "")
-		//if err != nil {
-		//	panic(err)
-		//}
-		//err = pprof.StartCPUProfile(profile)
-		//if err != nil {
-		//	panic(err)
-		//}
-
 		go func() {
 			sigs := make(chan os.Signal, 1)
 
 			signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
 
 			<-sigs
 
-			//pprof.StopCPUProfile()
-			//profile.Close()
-
-			//logger.Warn("Profile output", zap.String("Filename", profile.Name()))
-
 			os.RemoveAll(data)
 			os.Exit(0)
 		}()
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9f26eac and bd0dbea.

⛔ Files ignored due to path filters (1)
  • cli/go.sum is excluded by !**/*.sum
📒 Files selected for processing (16)
  • .idea/codeception.xml (0 hunks)
  • .idea/durable-php.iml (2 hunks)
  • .idea/php.xml (2 hunks)
  • .idea/phpspec.xml (0 hunks)
  • Dockerfile (1 hunks)
  • cli/Makefile (1 hunks)
  • cli/cli.go (3 hunks)
  • cli/glue/glue.go (1 hunks)
  • cli/go.mod (3 hunks)
  • cli/lib/api.go (1 hunks)
  • composer.json (1 hunks)
  • src/Events/EventQueue.php (3 hunks)
  • src/Events/TaskFailed.php (1 hunks)
  • src/Glue/glue.php (4 hunks)
  • src/RemoteOrchestrationClient.php (4 hunks)
  • tests/ClientTestCli.php (3 hunks)
💤 Files with no reviewable changes (2)
  • .idea/codeception.xml
  • .idea/phpspec.xml
✅ Files skipped from review due to trivial changes (7)
  • tests/ClientTestCli.php
  • Dockerfile
  • cli/lib/api.go
  • .idea/durable-php.iml
  • src/Glue/glue.php
  • src/Events/EventQueue.php
  • .idea/php.xml
🚧 Files skipped from review as they are similar to previous changes (1)
  • cli/go.mod
🧰 Additional context used
🪛 checkmake (0.2.2)
cli/Makefile

[warning] 1-1: Missing required phony target "all"

(minphony)


[warning] 1-1: Missing required phony target "clean"

(minphony)


[warning] 1-1: Missing required phony target "test"

(minphony)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: build-osx (arm64)
  • GitHub Check: build-linux (arm64)
  • GitHub Check: build-linux (amd64)
  • GitHub Check: build-docker
  • GitHub Check: Unit Tests - PHP
🔇 Additional comments (8)
src/Events/TaskFailed.php (1)

47-48: LGTM! Improved type consistency and clarity.

The change from string with default null to explicit string|null makes the method signature consistent with the constructor's parameter types and provides better type safety. This correctly reflects that these parameters can accept either a string or null value.

cli/glue/glue.go (1)

171-171: LGTM! Consistent logger option removal.

The removal of frankenphp.WithRequestLogger(logger) aligns with the coordinated simplification of FrankenPHP logging configuration across the CLI codebase.

cli/cli.go (1)

203-203: LGTM! Consistent FrankenPHP options simplification.

The removal of the logger option from FrankenPHP initialization aligns with the coordinated cleanup across the CLI codebase, maintaining only the essential thread count configuration.

composer.json (2)

40-40: LGTM! Version bump aligns with API changes.

The withinboredom/time package major version bump from v5 to v6 is properly coordinated with the corresponding code changes that update TimeUnit to Unit throughout the codebase.


36-36: Assess the PHP 8.4 Requirement and Compatibility

The version constraint in composer.json was bumped from >=8.3 to >=8.4 (line 36). PHP 8.4 brings major features (e.g., property hooks, asymmetric visibility, new array functions, enhanced JIT, HTTP/3 in cURL) but is only installed on ~13.7% of PHP sites as of mid-2025 and still in “beta support” on WordPress.

Please verify:

  • Whether the codebase actually uses any PHP 8.4-only features (e.g., array_find, property hooks, asymmetric visibility).
  • That your CI pipelines, hosting environments, and any CMS/platform dependencies (WordPress, Drupal, package ecosystem) fully support PHP 8.4.
  • If you’re not leveraging 8.4-specific functionality, consider reverting to >=8.3 for broader compatibility.

Files to review:

  • composer.json (line 36)
src/RemoteOrchestrationClient.php (3)

38-38: LGTM! Import updated for new package version.

The import statement correctly reflects the API change from TimeUnit to Unit in the withinboredom/time v6 package.


52-52: LGTM! Improved multibyte string handling.

The change from rtrim to mb_rtrim ensures proper handling of multibyte characters in the API host string, which is a good improvement for internationalization support.


171-173: LGTM! Timeout configurations updated for new API.

The timeout method calls correctly use the new Unit::Seconds constant instead of the deprecated TimeUnit::Seconds, maintaining the same timeout values while adapting to the updated package API.

Signed-off-by: Robert Landers <landers.robert@gmail.com>
Signed-off-by: Robert Landers <landers.robert@gmail.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
src/Proxy/ClientProxy.php (1)

121-126: Same unused parameter issue as OrchestratorProxy.

Consider applying the same fix suggested for OrchestratorProxy.

🧹 Nitpick comments (2)
src/Proxy/OrchestratorProxy.php (1)

112-117: Consider removing unused parameter.

The $class parameter is not used in the preamble method implementation.

-protected function preamble(ReflectionClass $class): string
+protected function preamble(ReflectionClass $class): string // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter

Or update the abstract class to make this parameter optional if it's not needed in all implementations.

src/Proxy/SpyProxy.php (1)

38-84: Hook implementation looks good, but consider method name handling.

The hook-specific logic correctly generates simplified get/set hooks without parameters or return types, which aligns with the pattern in other proxy classes. The $getHook variable usage is correct despite the static analysis warning.

However, consider ensuring method names are handled consistently:

 protected function impureCall(ReflectionMethod $method, bool $isHook = false): string
 {
     $getHook = 'return ';
     if ($isHook && str_ends_with($method->getName(), 'get')) {
         $name = 'get';
     } elseif ($isHook && str_ends_with($method->getName(), 'set')) {
         $name = 'set';
         $getHook = '';
     } else {
-        $name = $method->getName();
+        $name = $isHook ? $method->getName() : $method->getName();
     }

Actually, the current implementation is fine - the $name variable correctly holds the method name for non-hook cases.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bd0dbea and 63ee492.

📒 Files selected for processing (8)
  • .idea/php.xml (3 hunks)
  • cli/lib/api.go (3 hunks)
  • src/Proxy/ClientProxy.php (4 hunks)
  • src/Proxy/Generator.php (8 hunks)
  • src/Proxy/OrchestratorProxy.php (4 hunks)
  • src/Proxy/SpyProxy.php (3 hunks)
  • tests/Feature/ClientProxyTest.php (3 hunks)
  • tests/Feature/OrchestratorProxyTest.php (4 hunks)
✅ Files skipped from review due to trivial changes (1)
  • cli/lib/api.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • .idea/php.xml
🧰 Additional context used
🧬 Code Graph Analysis (2)
src/Proxy/Generator.php (3)
src/Proxy/ClientProxy.php (5)
  • getName (73-76)
  • impureCall (83-119)
  • pureMethod (33-71)
  • preamble (121-126)
  • impureSignal (78-81)
src/Proxy/OrchestratorProxy.php (5)
  • getName (81-84)
  • impureCall (38-79)
  • pureMethod (33-36)
  • preamble (112-117)
  • impureSignal (86-110)
src/Proxy/SpyProxy.php (5)
  • getName (86-89)
  • impureCall (38-84)
  • pureMethod (33-36)
  • preamble (96-101)
  • impureSignal (91-94)
src/Proxy/SpyProxy.php (3)
src/Proxy/Generator.php (6)
  • Generator (35-156)
  • pureMethod (129-129)
  • impureCall (133-133)
  • getName (65-65)
  • impureSignal (131-131)
  • preamble (155-155)
src/Proxy/ClientProxy.php (5)
  • pureMethod (33-71)
  • impureCall (83-119)
  • getName (73-76)
  • impureSignal (78-81)
  • preamble (121-126)
src/Proxy/OrchestratorProxy.php (5)
  • pureMethod (33-36)
  • impureCall (38-79)
  • getName (81-84)
  • impureSignal (86-110)
  • preamble (112-117)
🪛 PHPMD (2.15.0)
src/Proxy/OrchestratorProxy.php

112-112: Avoid unused parameters such as '$class'. (Unused Code Rules)

(UnusedFormalParameter)

src/Proxy/SpyProxy.php

33-33: Avoid unused parameters such as '$isHook'. (Unused Code Rules)

(UnusedFormalParameter)


40-40: Avoid unused local variables such as '$getHook'. (Unused Code Rules)

(UnusedLocalVariable)


96-96: Avoid unused parameters such as '$class'. (Unused Code Rules)

(UnusedFormalParameter)

src/Proxy/ClientProxy.php

121-121: Avoid unused parameters such as '$class'. (Unused Code Rules)

(UnusedFormalParameter)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: build-osx (arm64)
  • GitHub Check: build-osx (x86_64)
  • GitHub Check: build-linux (amd64)
  • GitHub Check: build-linux (arm64)
  • GitHub Check: build-docker
  • GitHub Check: Unit Tests - PHP
🔇 Additional comments (10)
tests/Feature/OrchestratorProxyTest.php (2)

31-38: LGTM! Proper test coverage for property hooks.

The addition of the public property with getter/setter hooks correctly tests the new proxy generation feature for PHP 8.4 property hooks.


48-52: Good improvement: Snapshot testing for generated proxies.

Using snapshot assertions instead of hardcoded string comparisons improves test maintainability.

tests/Feature/ClientProxyTest.php (2)

26-36: Good consistency with test structure.

The property addition matches the OrchestratorProxyTest, and the test rename improves clarity by specifying "client proxy".

Also applies to: 46-46


56-58: Correct implementation of interface property.

The anonymous class properly implements the new prop property required by the interface.

src/Proxy/OrchestratorProxy.php (1)

38-79: Well-implemented property hook support.

The implementation correctly handles both getter and setter hooks, preserving the original method names for entity calls while generating appropriate proxy methods.

src/Proxy/Generator.php (1)

99-126: Excellent implementation of property hook generation.

The property generation logic correctly:

  • Handles both getter and setter hooks
  • Preserves type information
  • Filters out empty hooks for clean output
  • Integrates seamlessly with the existing proxy generation flow
src/Proxy/ClientProxy.php (2)

35-64: Setter hook implementation looks good.

The implementation correctly generates setter hooks that delegate to __set methods on the source object. Note that this assumes a specific naming convention for the generated methods.


85-112: Correct implementation of purity constraints.

Getter hooks appropriately throw ImpureException to maintain purity constraints in client proxies.

src/Proxy/SpyProxy.php (2)

27-29: LGTM: Import statements cleaned up properly.

The import statements have been properly updated to use the reflection classes without leading backslashes, which is consistent with modern PHP practices and aligns with similar changes in other proxy classes.


86-101: LGTM: Method signatures updated for consistency.

The type hints have been properly updated to use the imported reflection classes without leading backslashes. The unused parameter warning for $class in preamble is a false positive since it's required by the abstract parent class signature.

Signed-off-by: Robert Landers <landers.robert@gmail.com>
Signed-off-by: Robert Landers <landers.robert@gmail.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🔭 Outside diff range comments (1)
src/Proxy/SpyProxy.php (1)

38-89: Fix unused variable and undefined variable issues.

Two issues in the hook implementation:

  1. The $getHook variable is declared but never used in the hook template
  2. The $value variable is referenced but not defined in the current scope

Apply this fix:

 protected function impureCall(ReflectionMethod $method, bool $isHook = false): string
 {
-    $getHook = 'return ';
     if ($isHook && str_ends_with($method->getName(), 'get')) {
         $name = 'get';
     } elseif ($isHook && str_ends_with($method->getName(), 'set')) {
         $name = 'set';
-        $getHook = '';
     } else {
         $name = $method->getName();
     }
 
     // ... rest of method
     
     if ($isHook) {
         $hookName = $method->getName();
-        if (str_ends_with($hookName, 'get')) {
-            $value = '[$value]';
-        } else {
-            $value = '[]';
-        }
+        $value = str_ends_with($hookName, 'get') ? '[]' : '[$value]';
         return <<<EOT
             {$name} {
               \$this->operation = "{$hookName}";
               \$this->arguments = {$value};
               throw new \Exception('Not implemented');
             }
             EOT;
     }
♻️ Duplicate comments (1)
src/Proxy/SpyProxy.php (1)

33-36: Pass the $isHook parameter to maintain consistency.

The $isHook parameter is not being passed to impureCall, which breaks consistency with other proxy implementations and makes the parameter unused.

Apply this fix:

 protected function pureMethod(ReflectionMethod $method, bool $isHook = false): string
 {
-    return $this->impureCall($method);
+    return $this->impureCall($method, $isHook);
 }
🧹 Nitpick comments (2)
src/Proxy/OrchestratorProxy.php (1)

117-122: Consider removing unused parameter if not required by interface.

The $class parameter is not used in the method body. If this parameter is not required by the parent class interface, consider removing it to clean up the method signature.

-protected function preamble(ReflectionClass $class): string
+protected function preamble(): string
src/Proxy/SpyProxy.php (1)

101-106: Consider removing unused parameter if not required by interface.

The $class parameter is not used in the method body. If this parameter is not required by the parent class interface, consider removing it to clean up the method signature.

-protected function preamble(ReflectionClass $class): string
+protected function preamble(): string
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 63ee492 and eaaa1a0.

📒 Files selected for processing (2)
  • src/Proxy/OrchestratorProxy.php (4 hunks)
  • src/Proxy/SpyProxy.php (3 hunks)
🧰 Additional context used
🪛 PHPMD (2.15.0)
src/Proxy/SpyProxy.php

33-33: Avoid unused parameters such as '$isHook'. (Unused Code Rules)

(UnusedFormalParameter)


40-40: Avoid unused local variables such as '$getHook'. (Unused Code Rules)

(UnusedLocalVariable)


101-101: Avoid unused parameters such as '$class'. (Unused Code Rules)

(UnusedFormalParameter)

src/Proxy/OrchestratorProxy.php

117-117: Avoid unused parameters such as '$class'. (Unused Code Rules)

(UnusedFormalParameter)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: build-linux (amd64)
  • GitHub Check: build-osx (arm64)
  • GitHub Check: build-linux (arm64)
  • GitHub Check: build-docker
  • GitHub Check: Unit Tests - PHP
🔇 Additional comments (3)
src/Proxy/OrchestratorProxy.php (2)

33-36: LGTM! Parameter delegation implemented correctly.

The $isHook parameter is properly passed through to impureCall, maintaining consistency with the updated method signature.


38-84: No undefined $value—approving changes.

The $value variable is explicitly assigned in both branches of the hook case before being interpolated, so there’s no undefined reference.

src/Proxy/SpyProxy.php (1)

27-30: LGTM! Import cleanup follows PHP standards.

Removing leading backslashes from use statements is the correct approach and aligns with PSR-12 coding standards.

Signed-off-by: Robert Landers <landers.robert@gmail.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
src/Proxy/Generator.php (1)

27-33: PropertyHookType import issue persists.

This is the same issue previously identified - the PropertyHookType import still lacks its proper namespace qualification.

🧹 Nitpick comments (1)
src/Proxy/SpyProxy.php (1)

38-90: Hook implementation works correctly for spy functionality.

The hook logic properly handles property getter/setter scenarios for the spy proxy, setting appropriate operation tracking and throwing the expected "Not implemented" exception.

However, there's a minor cleanup opportunity:

-    $getHook = true;
     if ($isHook && str_ends_with($method->getName(), 'get')) {
         $name = 'get';
     } elseif ($isHook && str_ends_with($method->getName(), 'set')) {
         $name = 'set';
-        $getHook = false;
     } else {
         $name = $method->getName();
     }

The $getHook variable is set but never used since the condition directly checks the method name.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 356ca4c and be73d47.

📒 Files selected for processing (3)
  • src/Proxy/Generator.php (8 hunks)
  • src/Proxy/OrchestratorProxy.php (4 hunks)
  • src/Proxy/SpyProxy.php (3 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/Proxy/OrchestratorProxy.php (4)
src/Proxy/SpyProxy.php (4)
  • pureMethod (33-36)
  • impureCall (38-90)
  • getName (92-95)
  • preamble (102-107)
src/Proxy/Generator.php (4)
  • pureMethod (129-129)
  • impureCall (133-133)
  • getName (65-65)
  • preamble (155-155)
src/Proxy/ClientProxy.php (4)
  • pureMethod (33-71)
  • impureCall (83-119)
  • getName (73-76)
  • preamble (121-126)
src/EntityContext.php (1)
  • return (87-95)
🪛 PHPMD (2.15.0)
src/Proxy/OrchestratorProxy.php

118-118: Avoid unused parameters such as '$class'. (Unused Code Rules)

(UnusedFormalParameter)

src/Proxy/SpyProxy.php

40-40: Avoid unused local variables such as '$getHook'. (Unused Code Rules)

(UnusedLocalVariable)


102-102: Avoid unused parameters such as '$class'. (Unused Code Rules)

(UnusedFormalParameter)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: build-osx (arm64)
  • GitHub Check: build-osx (x86_64)
  • GitHub Check: build-linux (arm64)
  • GitHub Check: build-linux (amd64)
  • GitHub Check: build-docker
  • GitHub Check: Unit Tests - PHP
🔇 Additional comments (13)
src/Proxy/OrchestratorProxy.php (4)

33-36: LGTM: Method signature correctly updated for hook support.

The pureMethod signature now properly matches the abstract method definition and correctly passes the $isHook parameter to impureCall.


38-85: Well-implemented hook support for property getters and setters.

The logic correctly differentiates between property getter and setter hooks:

  • Getters use return to provide the retrieved value
  • Setters omit return as they don't need to return a value
  • Both properly call through the orchestration context using waitOne and callEntity

The implementation maintains backward compatibility for non-hook method calls.


111-116: Good formatting improvements for consistency.

The indentation changes improve code readability and maintain consistent formatting across the class.


118-123: Formatting improvements enhance readability.

The consistent indentation improves code formatting. The static analysis warning about the unused $class parameter can be safely ignored as it's required by the abstract method signature.

src/Proxy/Generator.php (6)

41-42: Excellent import usage improvements.

Using imported class names instead of fully qualified names throughout the code significantly improves readability and maintainability.

Also applies to: 52-53, 65-65, 74-74, 79-79


99-117: Well-structured property hook generation.

The implementation correctly:

  • Retrieves public properties using reflection
  • Generates type-hinted property declarations
  • Adds getter/setter hooks when present using the hook-aware proxy methods
  • Filters out empty hooks to keep the generated code clean

This provides comprehensive support for PHP property hooks in proxy generation.


119-126: Class template properly integrates property generation.

The updated template correctly positions the generated properties before methods, following standard PHP class structure conventions.


129-129: Method signatures correctly updated for hook support.

Adding the optional $isHook parameter with a default value maintains backward compatibility while enabling the new property hook functionality.

Also applies to: 133-133


135-153: Type handling method improved with cleaner imports.

The updates to use imported reflection types improve code consistency and readability while maintaining the same functionality.


155-155: Preamble method signature updated consistently.

The signature update to use imported ReflectionClass maintains consistency with the overall import cleanup improvements.

src/Proxy/SpyProxy.php (3)

27-30: Clean import additions improve readability.

Adding proper import statements for reflection classes improves code consistency and readability throughout the file.


33-36: Previous feedback successfully addressed.

The method now correctly passes the $isHook parameter to impureCall, resolving the consistency issue identified in previous reviews.


92-95: Method signatures updated consistently with import cleanup.

The updates to use imported reflection classes improve consistency across the file. The static analysis warning about the unused $class parameter in preamble can be ignored as it's required by the abstract method interface.

Also applies to: 97-100, 102-107

Signed-off-by: Robert Landers <landers.robert@gmail.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between be73d47 and c7d4508.

📒 Files selected for processing (1)
  • src/State/EntityHistory.php (6 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: build-linux (arm64)
  • GitHub Check: build-linux (amd64)
  • GitHub Check: build-osx (x86_64)
  • GitHub Check: build-osx (arm64)
  • GitHub Check: build-docker
  • GitHub Check: Unit Tests - PHP
🔇 Additional comments (7)
src/State/EntityHistory.php (7)

71-78: LGTM! Improved constructor formatting.

The multiline parameter formatting with trailing commas enhances readability and makes future parameter additions cleaner in version control diffs.


165-165: LGTM! Cleaner anonymous class instantiation.

Removing the empty parentheses is the preferred PHP syntax when no constructor parameters are needed.


169-177: LGTM! Consistent multiline formatting.

The Status constructor formatting aligns with the class constructor style, improving code consistency and readability.


266-267: LGTM! Appropriate use of goto for control flow.

The goto label provides a clean way to avoid code duplication for the finalization logic when handling property operations.


288-291: LGTM! Improved array_filter readability.

The multiline formatting makes the filter logic more readable while maintaining the same functionality.


125-130: LGTM! Consistent multiline method call formatting.

The formatting aligns with the file's overall style and improves readability of nested method calls.


270-272: LGTM! Consistent formatting across similar constructs.

The multiline formatting matches the pattern used elsewhere in the file, maintaining consistency.

Signed-off-by: Robert Landers <landers.robert@gmail.com>
Signed-off-by: Robert Landers <landers.robert@gmail.com>
Signed-off-by: Robert Landers <landers.robert@gmail.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
src/Proxy/SpyProxy.php (1)

33-36: ✅ Previous issue resolved - parameter now properly passed through.

The $isHook parameter is now correctly passed to impureCall, addressing the consistency issue identified in previous reviews.

🧹 Nitpick comments (1)
src/Proxy/SpyProxy.php (1)

40-40: Remove unused variable.

The $getHook variable is assigned but never used in the method.

-        $getHook = true;
-        if ($isHook && str_ends_with($method->getName(), 'get')) {
+        if ($isHook && str_ends_with($method->getName(), 'get')) {
             $name = 'get';
         } elseif ($isHook && str_ends_with($method->getName(), 'set')) {
             $name = 'set';
-            $getHook = false;
         } else {
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6eb1748 and 6b53c03.

⛔ Files ignored due to path filters (2)
  • tests/.pest/snapshots/Feature/ClientProxyTest/it_generates_a_client_proxy_correctly.snap is excluded by !**/*.snap
  • tests/.pest/snapshots/Feature/OrchestratorProxyTest/it_generates_a_proxy_correctly.snap is excluded by !**/*.snap
📒 Files selected for processing (1)
  • src/Proxy/SpyProxy.php (3 hunks)
🧰 Additional context used
🪛 PHPMD (2.15.0)
src/Proxy/SpyProxy.php

40-40: Avoid unused local variables such as '$getHook'. (Unused Code Rules)

(UnusedLocalVariable)


102-102: Avoid unused parameters such as '$class'. (Unused Code Rules)

(UnusedFormalParameter)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: build-linux (arm64)
  • GitHub Check: build-docker
  • GitHub Check: build-linux (amd64)
  • GitHub Check: Unit Tests - PHP
🔇 Additional comments (4)
src/Proxy/SpyProxy.php (4)

27-30: LGTM! Import statement cleanup follows PHP best practices.

Removing the leading backslashes from the use statements is the correct approach and improves code consistency.


66-81: LGTM! Property hook generation logic is well-implemented.

The hook-specific code generation correctly handles getter/setter hooks with appropriate operation and argument handling. The differentiation between 'get' and 'set' hooks and the specialized method body generation aligns with property hook requirements.


92-92: LGTM! Method signatures updated consistently with import changes.

The method signatures correctly use the imported reflection classes, maintaining consistency with the import statement updates.

Also applies to: 97-97


102-107: No changes needed: $class parameter is required by the parent abstract method

The Generator base class declares an abstract method
• src/Proxy/Generator.php:155: abstract protected function preamble(ReflectionClass $class): string;
All subclasses must match this signature, so even if unused internally, the $class parameter cannot be removed.

Signed-off-by: Robert Landers <landers.robert@gmail.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/State/OrchestrationInstance.php (1)

27-28: Consistent import pattern with architectural refactoring.

The imports support the same refactoring pattern as EntityId.php. Note that Stringable import style changed from \Stringable to Stringable (without leading backslash) - ensure this style is consistent across the codebase.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6b53c03 and d6528ed.

📒 Files selected for processing (5)
  • .idea/durable-php.iml (2 hunks)
  • .idea/php.xml (3 hunks)
  • composer.json (1 hunks)
  • src/State/EntityId.php (1 hunks)
  • src/State/OrchestrationInstance.php (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • .idea/durable-php.iml
🚧 Files skipped from review as they are similar to previous changes (2)
  • composer.json
  • .idea/php.xml
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/State/EntityId.php (2)
src/State/OrchestrationInstance.php (1)
  • __construct (32-32)
src/State/Ids/StateId.php (1)
  • __construct (41-41)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: build-linux (amd64)
  • GitHub Check: build-linux (arm64)
  • GitHub Check: build-osx (x86_64)
  • GitHub Check: build-docker
  • GitHub Check: build-osx (arm64)
  • GitHub Check: Unit Tests - PHP
🔇 Additional comments (5)
src/State/EntityId.php (3)

28-28: New dependency import added for Record base class.

The import of Withinboredom\Record supports the architectural refactoring from readonly class to extending a record-based infrastructure.


39-39: Property visibility changed to protected(set) for controlled mutability.

The change from public properties to protected(set) maintains read access while restricting write access to the class hierarchy. This provides controlled mutability that aligns with the Record base class approach.


33-33: Ensure EntityId property access remains valid after switching to Record

Switching from a public readonly class to extends Record with protected(set) properties may break any direct reads of $entityId->name or $entityId->id. Please confirm that the Withinboredom\Record base class still exposes these values (e.g. via magic __get or public getters); if not, update all call sites to use the correct accessor method.

Key locations to verify:

  • src/State/EntityHistory.php around:
    $this->name = $this->id->toEntityId()->name;
  • Any other occurrences of ->name or ->id on EntityId instances
src/State/OrchestrationInstance.php (2)

30-30: Consistent architectural change: readonly to Record-based.

This matches the same pattern applied to EntityId.php, creating consistency in the state management refactoring. The change from readonly class to extending Record provides controlled mutability.


32-32: Property visibility consistently updated to protected(set).

The constructor properties follow the same pattern as EntityId.php, changing from public to protected(set) for controlled access. This maintains the consistency of the refactoring approach across state-related classes.

Signed-off-by: Robert Landers <landers.robert@gmail.com>
Signed-off-by: Robert Landers <landers.robert@gmail.com>
Signed-off-by: Robert Landers <landers.robert@gmail.com>
Signed-off-by: Robert Landers <landers.robert@gmail.com>
Signed-off-by: Robert Landers <landers.robert@gmail.com>
Signed-off-by: Robert Landers <landers.robert@gmail.com>
Signed-off-by: Robert Landers <landers.robert@gmail.com>
Signed-off-by: Robert Landers <landers.robert@gmail.com>
Signed-off-by: Robert Landers <landers.robert@gmail.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Nitpick comments (1)
cli/lib/api.go (1)

318-781: Consider refactoring to reduce code duplication.

The entity and orchestration endpoints have nearly identical logic. Consider extracting common functionality into helper functions to improve maintainability.

For example, you could create helper functions like:

func handleShareOwnership(writer http.ResponseWriter, request *http.Request, ctx context.Context, rm *auth.ResourceManager, stateId *glue.StateId, logger *zap.Logger, config *config.Config, newUserId string) {
    // Common sharing logic
}

func handleGrantPermission(writer http.ResponseWriter, request *http.Request, ctx context.Context, rm *auth.ResourceManager, stateId *glue.StateId, logger *zap.Logger, config *config.Config, grantType, user, operation string) {
    // Common granting logic
}

func handleRevokePermission(writer http.ResponseWriter, request *http.Request, ctx context.Context, rm *auth.ResourceManager, stateId *glue.StateId, logger *zap.Logger, config *config.Config, revokeType, user string) {
    // Common revocation logic
}

This would eliminate the duplication between entity and orchestration endpoints while maintaining the same functionality.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cba9f5d and 6c492ce.

📒 Files selected for processing (1)
  • cli/lib/api.go (5 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: build-linux (amd64)
  • GitHub Check: build-docker
  • GitHub Check: build-osx (arm64)
  • GitHub Check: build-linux (arm64)
  • GitHub Check: Unit Tests - PHP
🔇 Additional comments (3)
cli/lib/api.go (3)

102-104: LGTM! Consistent logger removal.

The removal of frankenphp.WithRequestLogger(logger) aligns with similar changes across the codebase and maintains consistency.


887-887: Verify if escaped quotes are needed in error message.

The added escaped quotes in the error message seem unnecessary for HTTP responses and may display incorrectly to clients.

-					http.Error(writer, "\"Internal Server Error\"", http.StatusInternalServerError)
+					http.Error(writer, "Internal Server Error", http.StatusInternalServerError)

The escaped quotes will likely show up as literal quote characters in the response body, which is not typical for HTTP error messages.


947-947: LGTM! Typo fix.

Correctly fixes the spelling from "Unkown" to "Unknown" in the log message.

Signed-off-by: Robert Landers <landers.robert@gmail.com>
Signed-off-by: Robert Landers <landers.robert@gmail.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

♻️ Duplicate comments (3)
cli/lib/api.go (3)

691-691: Replace http.Error with WriteHeader for success response.

Same issue as the entity sharing endpoint - using http.Error for success responses is inconsistent.

-		http.Error(writer, "", http.StatusOK)
+		writer.WriteHeader(http.StatusOK)

694-767: Orchestration grant endpoint needs missing context and logging.

The handler is missing correlation ID handling and request logging that other endpoints have.

Add the missing context and logging after the method validation:

 		if request.Method != "PUT" {
 			http.Error(writer, "Method Not Allowed", http.StatusMethodNotAllowed)
 			return
 		}
 
+		ctx := getCorrelationId(ctx, &request.Header, nil)
+		logRequest(logger, request, ctx)
+
 		vars := mux.Vars(request)

769-819: Orchestration revoke endpoint needs missing context and logging.

The handler is missing correlation ID handling and request logging that other endpoints have.

Add the missing context and logging after the method validation:

 		if request.Method != "DELETE" {
 			http.Error(writer, "Method Not Allowed", http.StatusMethodNotAllowed)
 			return
 		}
 
+		ctx := getCorrelationId(ctx, &request.Header, nil)
+		logRequest(logger, request, ctx)
+
 		vars := mux.Vars(request)
🧹 Nitpick comments (1)
cli/lib/api.go (1)

369-369: Replace http.Error with WriteHeader for success response.

Using http.Error with an empty message for a 200 OK response is unusual. Consider using writer.WriteHeader(http.StatusOK) instead for consistency with successful responses.

-		http.Error(writer, "", http.StatusOK)
+		writer.WriteHeader(http.StatusOK)
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6c492ce and 932d784.

📒 Files selected for processing (6)
  • cli/lib/api.go (5 hunks)
  • src/DurableClient.php (3 hunks)
  • src/EntityClientInterface.php (2 hunks)
  • src/OrchestrationClientInterface.php (2 hunks)
  • src/RemoteEntityClient.php (6 hunks)
  • src/RemoteOrchestrationClient.php (7 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/EntityClientInterface.php (4)
cli/auth/user.go (1)
  • Operation (11-11)
src/DurableClient.php (5)
  • shareEntityOwnership (147-150)
  • grantEntityAccessToUser (152-155)
  • grantEntityAccessToRole (157-160)
  • revokeEntityAccessToUser (162-165)
  • revokeEntityAccessToRole (167-170)
src/RemoteEntityClient.php (5)
  • shareEntityOwnership (168-178)
  • grantEntityAccessToUser (180-190)
  • grantEntityAccessToRole (192-202)
  • revokeEntityAccessToUser (204-214)
  • revokeEntityAccessToRole (216-226)
src/State/EntityId.php (1)
  • EntityId (33-51)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: build-docker
  • GitHub Check: build-osx (arm64)
  • GitHub Check: build-osx (x86_64)
  • GitHub Check: build-linux (amd64)
  • GitHub Check: build-linux (arm64)
  • GitHub Check: Unit Tests - PHP
🔇 Additional comments (26)
src/EntityClientInterface.php (2)

27-27: LGTM! Clean import addition.

The import of the Operation class is properly placed and follows the existing import conventions in the file.


85-94: Well-designed access control interface methods.

The five new methods provide a comprehensive access control API with consistent signatures:

  • Clear separation between ownership sharing and permission grants
  • Type-safe operation specification using the Operation enum
  • Consistent parameter naming and ordering
  • Proper distinction between user and role-based permissions

The interface design aligns well with the corresponding implementations in RemoteEntityClient.php and the API endpoints in cli/lib/api.go.

src/RemoteOrchestrationClient.php (6)

30-30: LGTM! Proper import for access control operations.

The import of the Operation class is correctly added to support the new access control methods.


39-39: Good modernization with time unit import.

The change from TimeUnit to Unit appears to be part of a broader refactoring to modernize time handling across the codebase.


53-53: Excellent use of multibyte-safe string function.

The switch from rtrim() to mb_rtrim() ensures proper handling of multibyte characters in API host URLs, which is important for internationalization support.


151-151: Good use of factory method for StateId creation.

Using StateId::fromString() instead of direct construction is a good practice that provides better encapsulation and consistency across the codebase.


172-174: Consistent timeout handling with updated time units.

The timeout configuration properly uses the new Unit::Seconds enum and maintains the same timeout values (1 hour inactivity/transfer, 30 seconds connect).


197-255: Comprehensive orchestration access control implementation.

The six new methods provide complete access control functionality:

  • Consistent HTTP request patterns: All methods follow the same structure with proper URL encoding, authorization headers, and error handling
  • Proper error handling: Each method checks for non-200 status codes and throws descriptive exceptions
  • RESTful API design: Uses appropriate HTTP methods (PUT for grants, DELETE for revokes)
  • Type safety: Uses the Operation enum for specifying permission types

The implementation mirrors the entity access control methods, providing a consistent API experience across the codebase.

src/OrchestrationClientInterface.php (5)

27-27: LGTM! Proper import for access control operations.

The import of the Operation class is correctly added to support the new access control method signatures.


30-30: Good import addition for Generator type.

Adding the explicit Generator import improves code clarity and follows PHP best practices for type declarations.


38-38: Improved return type specification.

The change from \Generator to Generator with the explicit import is cleaner and more consistent with modern PHP practices.


48-48: Clean nullable type syntax.

The simplification from string|null to ?string is more concise and follows modern PHP nullable type conventions.


56-65: Well-designed orchestration access control interface.

The six new methods provide comprehensive access control functionality with:

  • Consistent naming convention: Methods follow the pattern {action}Orchestration{AccessType}To{TargetType}
  • Type safety: Uses OrchestrationInstance and Operation types appropriately
  • Clear separation of concerns: Distinct methods for sharing ownership vs granting/revoking specific permissions
  • User/role flexibility: Separate methods for user and role-based permissions

The interface design matches the entity access control methods, providing API consistency across the system.

src/DurableClient.php (3)

28-28: LGTM! Proper import for access control operations.

The import of the Operation class is correctly added to support the new access control method signatures.


147-170: Excellent facade implementation for entity access control.

The five entity access control methods properly delegate to the underlying entityClient:

  • Clean delegation pattern: Each method simply passes through parameters to the appropriate client method
  • Consistent signatures: Method signatures match the interface definitions exactly
  • Proper encapsulation: The facade hides the complexity of managing separate clients
  • Type safety: Uses EntityId and Operation types appropriately

This implementation provides a unified API while maintaining separation of concerns.


172-195: Excellent facade implementation for orchestration access control.

The five orchestration access control methods properly delegate to the underlying orchestrationClient:

  • Parallel design: Methods mirror the entity access control methods for consistency
  • Clean delegation: Simple pass-through to the orchestration client
  • Type consistency: Uses OrchestrationInstance and Operation types appropriately
  • Unified interface: Provides single entry point for both entity and orchestration operations

The implementation maintains the facade pattern while providing comprehensive access control functionality.

cli/lib/api.go (6)

104-104: LGTM! Simplified FrankenPHP request creation.

The removal of frankenphp.WithRequestLogger(logger) aligns with similar simplifications mentioned in the PR summary across cli/glue/glue.go and cli/cli.go.


985-985: Good typo fix.

Corrected "Unkown" to "Unknown" in the log message.


318-370: Entity sharing endpoint implementation looks good.

The handler properly implements entity ownership sharing with:

  • CORS handling and method validation
  • Proper authorization check with auth.Owner permission
  • Resource discovery with error handling
  • Ownership sharing operation with error handling
  • Resource update with error handling
  • Appropriate logging

The implementation addresses the authorization and error handling patterns correctly.


640-692: Orchestration sharing endpoint implementation looks good.

The handler properly implements orchestration ownership sharing with all the required components:

  • CORS and method validation
  • Context and logging setup
  • Authorization check with auth.Owner permission
  • Resource discovery and error handling
  • Ownership sharing with proper error handling
  • Resource update with error handling
  • Appropriate logging

The implementation follows the same pattern as the entity sharing endpoint.


465-465: Permission level verified
The auth.ShareMinus permission is explicitly defined as “whether the share can see other shares and manage them,” and both the API’s authorize(..., auth.ShareMinus) call and the RevokeUser/RevokeRole methods enforce this same permission. No changes needed.


390-390: No change required: SharePlus correctly governs share invitations
The SharePlus operation is explicitly defined as “invite more shares” (cli/auth/user.go) and is consistently used in both authorize() and Resource.Grant*() methods to guard granting any share-based permissions. Requiring Owner here would be overly broad—SharePlus is the intended permission level for this endpoint.

src/RemoteEntityClient.php (4)

29-30: LGTM: Import additions support new functionality.

The new imports for Operation and SpyException are correctly added and used throughout the file for the entity sharing functionality and improved exception handling.


52-52: Good improvement: Using multibyte-safe string trimming.

Switching from rtrim() to mb_rtrim() ensures proper handling of API host URLs that may contain multibyte characters.


61-65: LGTM: Improved code formatting.

The multiline formatting of the Request instantiation with trailing commas improves readability and follows PHP best practices.


83-100: Excellent improvements to exception handling and code clarity.

The changes implement several good practices:

  • Specific exception catching (SpyException vs Throwable) for more precise error handling
  • Defensive programming with null initialization and early return guard
  • Consistent use of the EntityId() factory function
  • Improved code formatting with multiline method calls

Signed-off-by: Robert Landers <landers.robert@gmail.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
cli/glue/glue.go (1)

131-141: Consider more graceful error handling instead of panic.

The authorization context integration looks good. However, using panic for errors from DiscoverResource could crash the entire process. Consider returning an error or handling it more gracefully, especially since this appears to be in a request handling path.

-	rm := auth.GetResourceManager(ctx, stream)
-	res, err := rm.DiscoverResource(ctx, id, logger, true)
-	if err != nil {
-		logger.Error("DiscoverResource", zap.Error(err))
-		panic(err)
-	}
-	if res != nil {
-		ac, _ := rm.ToAuthContext(ctx, res)
-		headers.Add("DPHP_AUTH_CONTEXT", string(ac))
-	}
+	rm := auth.GetResourceManager(ctx, stream)
+	res, err := rm.DiscoverResource(ctx, id, logger, true)
+	if err != nil {
+		logger.Error("DiscoverResource", zap.Error(err))
+		// Consider returning error to caller instead of panic
+		writer.status = http.StatusInternalServerError
+		return writer.events, writer.Header(), writer.status, writer.DeleteAfter
+	}
+	if res != nil {
+		ac, err := rm.ToAuthContext(ctx, res)
+		if err != nil {
+			logger.Warn("Failed to convert resource to auth context", zap.Error(err))
+		} else {
+			headers.Add("DPHP_AUTH_CONTEXT", string(ac))
+		}
+	}
cli/auth/resourceManager.go (1)

92-131: Consider using structs for cleaner JSON marshaling.

The manual construction of maps for JSON marshaling is verbose and error-prone. Consider defining structs with appropriate JSON tags for a cleaner, more maintainable approach.

+type authContextJSON struct {
+    ContextID contextID `json:"contextId"`
+    Owners    []share   `json:"owners"`
+    Shares    []share   `json:"shares"`
+}
+
+type contextID struct {
+    ID string `json:"id"`
+}
+
+type share struct {
+    ShareType string   `json:"shareType"`
+    Subject   string   `json:"subject"`
+    Allowed   []string `json:"allowed"`
+}
+
 func (r *ResourceManager) ToAuthContext(ctx context.Context, resource *Resource) ([]byte, error) {
-    var owners []map[string]interface{}
+    authCtx := authContextJSON{
+        ContextID: contextID{ID: resource.id.String()},
+        Owners:    make([]share, 0, len(resource.Owners)),
+        Shares:    make([]share, 0, len(resource.Shares)),
+    }

     for o, _ := range resource.Owners {
-        owners = append(owners, map[string]interface{}{
-            "shareType": "owner",
-            "subject":   string(o),
-            "allowed":   []string{string(Owner)},
+        authCtx.Owners = append(authCtx.Owners, share{
+            ShareType: "owner",
+            Subject:   string(o),
+            Allowed:   []string{string(Owner)},
         })
     }

-    var shares []map[string]interface{}
-
     for _, s := range resource.Shares {
         if u, ok := s.(*UserShare); ok {
-            shares = append(shares, map[string]interface{}{
-                "shareType": "user",
-                "subject":   string(u.UserId),
-                "allowed":   maps.Keys(u.AllowedOperations),
+            authCtx.Shares = append(authCtx.Shares, share{
+                ShareType: "user",
+                Subject:   string(u.UserId),
+                Allowed:   maps.Keys(u.AllowedOperations),
             })
         }
         if r, ok := s.(*RoleShare); ok {
-            shares = append(shares, map[string]interface{}{
-                "shareType": "role",
-                "subject":   string(r.Role),
-                "allowed":   maps.Keys(r.AllowedOperations),
+            authCtx.Shares = append(authCtx.Shares, share{
+                ShareType: "role",
+                Subject:   string(r.Role),
+                Allowed:   maps.Keys(r.AllowedOperations),
             })
         }
     }

-    c := map[string]interface{}{
-        "contextId": map[string]string{
-            "id": resource.id.String(),
-        },
-        "owners": owners,
-        "shares": shares,
-    }
-
-    return json.Marshal(c)
+    return json.Marshal(authCtx)
 }
src/Contexts/AuthContext.php (1)

28-35: Consider error handling for deserialization failures.

The implementation is correct, but consider adding error handling for cases where the header exists but contains invalid serialized data.

 public static function fromCurrentContext(): ?AuthContext
 {
     if (isset($_SERVER['HTTP_DPHP_AUTH_CONTEXT'])) {
-        return Serializer::deserialize($_SERVER['HTTP_DPHP_AUTH_CONTEXT'], self::class);
+        try {
+            return Serializer::deserialize($_SERVER['HTTP_DPHP_AUTH_CONTEXT'], self::class);
+        } catch (Exception $e) {
+            // Log the error or handle as appropriate for your use case
+            return null;
+        }
     }

     return null;
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 932d784 and 5e8cb01.

📒 Files selected for processing (13)
  • cli/auth/resourceManager.go (2 hunks)
  • cli/glue/glue.go (3 hunks)
  • composer.json (2 hunks)
  • src/Contexts/AuthContext.php (1 hunks)
  • src/Contexts/AuthContext/Share.php (1 hunks)
  • src/Contexts/AuthContext/Share/Owner.php (1 hunks)
  • src/Contexts/AuthContext/Share/Role.php (1 hunks)
  • src/Contexts/AuthContext/Share/User.php (1 hunks)
  • src/Contexts/AuthContext/functions.php (1 hunks)
  • src/EntityContext.php (3 hunks)
  • src/EntityContextInterface.php (2 hunks)
  • src/Events/RevokeRole.php (2 hunks)
  • src/Events/RevokeUser.php (2 hunks)
✅ Files skipped from review due to trivial changes (3)
  • src/Contexts/AuthContext/Share/Role.php
  • src/Contexts/AuthContext/Share/User.php
  • src/Contexts/AuthContext/Share/Owner.php
🚧 Files skipped from review as they are similar to previous changes (1)
  • composer.json
🧰 Additional context used
🧬 Code Graph Analysis (6)
src/Events/RevokeUser.php (1)
src/Events/RevokeRole.php (2)
  • __construct (34-37)
  • completely (39-42)
src/EntityContext.php (8)
src/Events/GiveOwnership.php (1)
  • GiveOwnership (28-44)
src/Events/ShareOwnership.php (1)
  • ShareOwnership (28-44)
cli/auth/user.go (1)
  • Operation (11-11)
src/State/Ids/StateId.php (1)
  • fromEntityId (68-71)
src/EntityContextInterface.php (6)
  • shareOwnership (117-117)
  • giveOwnership (127-127)
  • grantUser (119-119)
  • grantRole (121-121)
  • revokeUser (123-123)
  • revokeRole (125-125)
src/Events/WithEntity.php (2)
  • WithEntity (29-59)
  • forInstance (36-43)
src/Events/RevokeRole.php (1)
  • completely (39-42)
src/Events/RevokeUser.php (1)
  • completely (39-42)
src/Contexts/AuthContext/functions.php (5)
src/Contexts/AuthContext.php (1)
  • AuthContext (12-36)
cli/auth/user.go (2)
  • Share (67-70)
  • Operation (11-11)
src/Contexts/AuthContext/Share/Owner.php (1)
  • Owner (29-29)
src/Contexts/AuthContext/Share/Role.php (1)
  • Role (7-7)
src/Contexts/AuthContext/Share/User.php (1)
  • User (7-7)
src/EntityContextInterface.php (1)
src/EntityContext.php (6)
  • shareOwnership (199-207)
  • grantUser (219-227)
  • grantRole (229-237)
  • revokeUser (239-247)
  • revokeRole (249-257)
  • giveOwnership (209-217)
src/Contexts/AuthContext.php (2)
src/Contexts/AuthContext/Share/Owner.php (1)
  • Owner (29-29)
src/Contexts/AuthContext/functions.php (1)
  • Owner (11-16)
src/Contexts/AuthContext/Share.php (6)
src/Contexts/AuthContext.php (1)
  • AuthContext (12-36)
cli/auth/user.go (2)
  • Share (67-70)
  • Operation (11-11)
src/Contexts/AuthContext/Share/Owner.php (1)
  • Owner (29-29)
src/Contexts/AuthContext/functions.php (3)
  • Owner (11-16)
  • Role (18-23)
  • User (25-30)
src/Contexts/AuthContext/Share/Role.php (1)
  • Role (7-7)
src/Contexts/AuthContext/Share/User.php (1)
  • User (7-7)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: build-linux (arm64)
  • GitHub Check: build-linux (amd64)
  • GitHub Check: build-docker
  • GitHub Check: Unit Tests - PHP
🔇 Additional comments (14)
cli/glue/glue.go (1)

184-184: LGTM!

The simplification of the FrankenPHP request creation by removing the logger option is appropriate.

src/Events/RevokeRole.php (3)

34-34: LGTM!

Using the nullable shorthand ?Operation is more concise and follows modern PHP conventions.


39-42: LGTM!

The rename to completely follows PHP naming conventions for static factory methods and is consistent with similar changes in related files.


46-46: Good catch!

Fixed the syntax error by removing the extraneous trailing comma in the sprintf call.

src/Events/RevokeUser.php (1)

34-42: LGTM!

The changes maintain consistency with RevokeRole.php:

  • Using nullable shorthand ?Operation
  • Renaming to completely following PHP conventions
  • Removing the unused StateId $target parameter simplifies the API
src/Contexts/AuthContext.php (2)

12-12: LGTM - Well-designed class declaration.

The abstract readonly class design is appropriate for an authorization context, preventing direct instantiation while allowing subclassing and ensuring immutability.


14-26: LGTM - Well-structured properties with proper serialization.

The property definitions are clean with appropriate type annotations and serialization attributes. The separation of $owners and $shares provides good architectural clarity.

src/Contexts/AuthContext/Share.php (2)

13-17: LGTM - Proper polymorphic serialization setup.

The StaticTypeMap configuration correctly maps discriminator values to their corresponding subclasses, enabling proper polymorphic deserialization.


18-26: LGTM - Clean property definitions for authorization model.

The properties are well-structured with proper type annotations and serialization attributes, supporting the authorization system's subject-operation model effectively.

src/EntityContext.php (3)

27-34: LGTM - Complete imports for authorization functionality.

The new imports properly support the added ownership and permission management methods with all necessary event classes and operation types.


141-141: LGTM - Consistent factory function usage.

The change from direct instantiation to the OrchestrationInstance() factory function aligns with the codebase-wide refactoring for consistency.


199-257: LGTM - Consistent and well-structured authorization methods.

All six authorization methods follow a clean, consistent pattern:

  • Event-driven architecture using the event dispatcher
  • Proper entity targeting with WithEntity::forInstance
  • Appropriate event classes with static factory methods
  • Variadic Operation parameters for flexible permission granting

The implementation integrates well with the existing event system and maintains architectural consistency.

src/EntityContextInterface.php (2)

27-27: LGTM - Necessary import for authorization methods.

The Operation import is required for the new authorization method signatures and is properly placed.


117-127: LGTM - Complete and consistent interface contract.

The method signatures properly define the authorization functionality contract:

  • Clear method names indicating their purpose
  • Appropriate parameter types with variadic Operation parameters for flexible permission granting
  • Consistent void return types for fire-and-forget operations

The interface matches the implementation in EntityContext.php exactly.

Signed-off-by: Robert Landers <landers.robert@gmail.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (9)
cli/lib/api.go (9)

394-394: Add missing correlation ID and request logging.

 		if request.Method != "PUT" {
 			http.Error(writer, "Method Not Allowed", http.StatusMethodNotAllowed)
 			return
 		}
 
+		ctx := getCorrelationId(ctx, &request.Header, nil)
+		logRequest(logger, request, ctx)
+
 		vars := mux.Vars(request)

469-469: Add missing correlation ID and request logging.

 		if request.Method != "DELETE" {
 			http.Error(writer, "Method Not Allowed", http.StatusMethodNotAllowed)
 			return
 		}
 
+		ctx := getCorrelationId(ctx, &request.Header, nil)
+		logRequest(logger, request, ctx)
+
 		vars := mux.Vars(request)

716-716: Add missing correlation ID and request logging.

 		if request.Method != "PUT" {
 			http.Error(writer, "Method Not Allowed", http.StatusMethodNotAllowed)
 			return
 		}
 
+		ctx := getCorrelationId(ctx, &request.Header, nil)
+		logRequest(logger, request, ctx)
+
 		vars := mux.Vars(request)

791-791: Add missing correlation ID and request logging.

 		if request.Method != "DELETE" {
 			http.Error(writer, "Method Not Allowed", http.StatusMethodNotAllowed)
 			return
 		}
 
+		ctx := getCorrelationId(ctx, &request.Header, nil)
+		logRequest(logger, request, ctx)
+
 		vars := mux.Vars(request)

937-937: Fix JSON encoding issue in error response.

The error response has extra quotes which will result in malformed JSON.

-					http.Error(writer, "\"Internal Server Error\"", http.StatusInternalServerError)
+					http.Error(writer, "Internal Server Error", http.StatusInternalServerError)

433-434: Add missing return statements and fix error responses.

 		if err != nil {
 			logger.Error("Failed to discover resource", zap.Error(err))
-			http.Error(writer, "", http.StatusNotFound)
+			http.Error(writer, "Not Found", http.StatusNotFound)
+			return
 		}
 
 		switch vars["type"] {
 		case "user":
 			err = r.GrantUser(auth.UserId(vars["user"]), operation, ctx)
 		case "role":
 			err = r.GrantRole(auth.Role(vars["user"]), operation, ctx)
 		}
 		if err != nil {
 			logger.Error("Failed to grant resource", zap.Error(err))
-			http.Error(writer, "", http.StatusForbidden)
+			http.Error(writer, "Forbidden", http.StatusForbidden)
+			return
 		}
 
 		err = r.Update(ctx, logger)
 		if err != nil {
 			logger.Error("Failed to update resource", zap.Error(err))
-			http.Error(writer, "", http.StatusInternalServerError)
+			http.Error(writer, "Internal Server Error", http.StatusInternalServerError)
+			return
 		}
 
-		http.Error(writer, "", http.StatusOK)
+		writer.WriteHeader(http.StatusOK)

Also applies to: 445-446, 452-453, 456-456


485-486: Add missing return statements and fix error responses.

 		if err != nil {
 			logger.Error("Failed to discover resource", zap.Error(err))
-			http.Error(writer, "", http.StatusNotFound)
+			http.Error(writer, "Not Found", http.StatusNotFound)
+			return
 		}
 
 		switch vars["type"] {
 		case "user":
 			err = r.RevokeUser(auth.UserId(vars["user"]), ctx)
 		case "role":
 			err = r.RevokeRole(auth.Role(vars["user"]), ctx)
 		}
 		if err != nil {
 			logger.Error("Failed to revoke resource", zap.Error(err))
-			http.Error(writer, "", http.StatusForbidden)
+			http.Error(writer, "Forbidden", http.StatusForbidden)
+			return
 		}
 
 		err = r.Update(ctx, logger)
 		if err != nil {
 			logger.Error("Failed to update resource", zap.Error(err))
-			http.Error(writer, "", http.StatusInternalServerError)
+			http.Error(writer, "Internal Server Error", http.StatusInternalServerError)
+			return
 		}
 
-		http.Error(writer, "", http.StatusOK)
+		writer.WriteHeader(http.StatusOK)

Also applies to: 497-498, 504-505, 508-508


755-756: Add missing return statements and fix error responses.

 		if err != nil {
 			logger.Error("Failed to discover resource", zap.Error(err))
-			http.Error(writer, "", http.StatusNotFound)
+			http.Error(writer, "Not Found", http.StatusNotFound)
+			return
 		}
 
 		switch vars["type"] {
 		case "user":
 			err = r.GrantUser(auth.UserId(vars["user"]), operation, ctx)
 		case "role":
 			err = r.GrantRole(auth.Role(vars["user"]), operation, ctx)
 		}
 		if err != nil {
 			logger.Error("Failed to grant resource", zap.Error(err))
-			http.Error(writer, "", http.StatusForbidden)
+			http.Error(writer, "Forbidden", http.StatusForbidden)
+			return
 		}
 
 		err = r.Update(ctx, logger)
 		if err != nil {
 			logger.Error("Failed to update resource", zap.Error(err))
-			http.Error(writer, "", http.StatusInternalServerError)
+			http.Error(writer, "Internal Server Error", http.StatusInternalServerError)
+			return
 		}
 
-		http.Error(writer, "", http.StatusOK)
+		writer.WriteHeader(http.StatusOK)

Also applies to: 767-768, 774-775, 778-778


807-808: Add missing return statements and fix error responses.

 		if err != nil {
 			logger.Error("Failed to discover resource", zap.Error(err))
-			http.Error(writer, "", http.StatusNotFound)
+			http.Error(writer, "Not Found", http.StatusNotFound)
+			return
 		}
 
 		switch vars["type"] {
 		case "user":
 			err = r.RevokeUser(auth.UserId(vars["user"]), ctx)
 		case "role":
 			err = r.RevokeRole(auth.Role(vars["user"]), ctx)
 		}
 		if err != nil {
 			logger.Error("Failed to revoke resource", zap.Error(err))
-			http.Error(writer, "", http.StatusForbidden)
+			http.Error(writer, "Forbidden", http.StatusForbidden)
+			return
 		}
 
 		err = r.Update(ctx, logger)
 		if err != nil {
 			logger.Error("Failed to update resource", zap.Error(err))
-			http.Error(writer, "", http.StatusInternalServerError)
+			http.Error(writer, "Internal Server Error", http.StatusInternalServerError)
+			return
 		}
 
-		http.Error(writer, "", http.StatusOK)
+		writer.WriteHeader(http.StatusOK)

Also applies to: 819-820, 826-827, 830-830

🧹 Nitpick comments (2)
cli/lib/api.go (2)

381-381: Use WriteHeader for successful responses.

Replace http.Error with WriteHeader for successful responses as there's no error message.

-		http.Error(writer, "", http.StatusOK)
+		writer.WriteHeader(http.StatusOK)

703-703: Use WriteHeader for successful responses.

-		http.Error(writer, "", http.StatusOK)
+		writer.WriteHeader(http.StatusOK)
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5e8cb01 and 053105c.

📒 Files selected for processing (13)
  • cli/auth/resource.go (5 hunks)
  • cli/auth/resourceManager.go (3 hunks)
  • cli/cli.go (11 hunks)
  • cli/glue/glue.go (7 hunks)
  • cli/glue/response_writer.go (3 hunks)
  • cli/glue/state.go (1 hunks)
  • cli/ids/id.go (2 hunks)
  • cli/lib/api.go (16 hunks)
  • cli/lib/billing.go (3 hunks)
  • cli/lib/consumer.go (6 hunks)
  • cli/lib/indexer.go (6 hunks)
  • cli/lib/locks.go (4 hunks)
  • src/Contexts/AuthContext.php (1 hunks)
✅ Files skipped from review due to trivial changes (5)
  • cli/ids/id.go
  • cli/glue/response_writer.go
  • cli/glue/state.go
  • cli/lib/locks.go
  • cli/auth/resource.go
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/Contexts/AuthContext.php
  • cli/auth/resourceManager.go
  • cli/cli.go
  • cli/glue/glue.go
🧰 Additional context used
🧬 Code Graph Analysis (3)
cli/lib/billing.go (2)
cli/ids/id.go (2)
  • StateId (176-179)
  • ParseStateId (118-130)
cli/glue/response_writer.go (3)
  • HeaderStateId (20-20)
  • HeaderEmittedAt (25-25)
  • HeaderEmittedBy (24-24)
cli/lib/indexer.go (4)
cli/config/config.go (1)
  • Config (66-72)
cli/ids/id.go (4)
  • IdKind (9-9)
  • Entity (13-13)
  • ParseStateId (118-130)
  • Orchestration (14-14)
cli/glue/state.go (1)
  • GetObjectStore (9-16)
cli/lib/index.go (1)
  • CreateOrchestrationIndex (39-74)
cli/lib/consumer.go (2)
cli/ids/id.go (3)
  • IdKind (9-9)
  • ParseStateId (118-130)
  • Entity (13-13)
cli/glue/response_writer.go (2)
  • HeaderStateId (20-20)
  • HeaderEmittedBy (24-24)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: build-osx (arm64)
  • GitHub Check: build-linux (arm64)
  • GitHub Check: build-docker
  • GitHub Check: build-linux (amd64)
  • GitHub Check: Unit Tests - PHP
🔇 Additional comments (7)
cli/lib/billing.go (1)

7-7: LGTM! Consistent migration to the ids package.

The changes correctly migrate state ID handling from the glue package to the ids package, which aligns with the broader refactoring effort across the codebase.

Also applies to: 46-46, 91-91, 93-93

cli/lib/indexer.go (1)

7-7: LGTM! Consistent migration to the ids package.

All references to IdKind type, constants (Entity, Orchestration), and the ParseStateId function have been correctly updated to use the ids package instead of glue.

Also applies to: 19-19, 25-25, 103-103, 123-123, 144-144, 152-152, 230-230

cli/lib/consumer.go (2)

9-9: LGTM! Consistent migration to the ids package.

All state ID parsing and kind comparisons have been correctly updated to use the ids package.

Also applies to: 20-20, 59-59, 102-103, 132-132


295-303: Authorization context injection looks good.

The resource discovery and authorization context injection follows the established error handling pattern (panic on error) and correctly adds the context to headers for downstream processing.

cli/lib/api.go (3)

8-8: LGTM! Consistent migration to the ids package.

All ID type references and related functions have been correctly updated from the glue package to the ids package throughout the file.

Also applies to: 105-105, 168-170, 259-259, 523-526, 639-642, 848-851, 914-914, 979-982, 1011-1011, 1081-1081, 1093-1093


997-997: Good catch on the typo fix.

Fixed "Unkown" to "Unknown" in the log message.


264-273: Authorization context injection implemented correctly.

The resource discovery and authorization context header injection follows the same pattern as in consumer.go and maintains consistency with the error handling approach in this function.

Signed-off-by: Robert Landers <landers.robert@gmail.com>
Signed-off-by: Robert Landers <landers.robert@gmail.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
cli/cli.go (1)

546-567: The input validation and error handling issues remain unaddressed.

The parsing logic for roles and claims still lacks proper validation as identified in the previous review. The code will fail with empty options, extra whitespace, and provides unclear error messages.

The previous review comment's suggestions for improving input validation, whitespace handling, and error messages are still applicable and should be implemented.

🧹 Nitpick comments (1)
cli/cli.go (1)

94-102: Remove commented CPU profiling code entirely.

The commented CPU profiling code should be removed completely rather than left as comments, as it creates unnecessary code clutter.

-		//profile, err := os.CreateTemp("", "")
-		//if err != nil {
-		//	panic(err)
-		//}
-		//err = pprof.StartCPUProfile(profile)
-		//if err != nil {
-		//	panic(err)
-		//}
-			//pprof.StopCPUProfile()
-			//profile.Close()
-
-			//logger.Warn("Profile output", zap.String("Filename", profile.Name()))

Also applies to: 110-113

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b6c8c5c and 87ae835.

📒 Files selected for processing (2)
  • cli/auth/keys.go (2 hunks)
  • cli/cli.go (11 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • cli/auth/keys.go
🧰 Additional context used
🧬 Code Graph Analysis (1)
cli/cli.go (2)
cli/ids/id.go (6)
  • Activity (12-12)
  • Entity (13-13)
  • Orchestration (14-14)
  • IdKind (9-9)
  • StateId (176-179)
  • ParseStateId (118-130)
cli/auth/keys.go (1)
  • CreateUser (117-143)
🔇 Additional comments (4)
cli/cli.go (4)

184-186: LGTM! Systematic package migration completed correctly.

The migration from glue package constants to ids package constants is consistent and aligns with the broader refactor described in the PR. All references have been properly updated.

Also applies to: 215-215, 220-220, 225-225, 232-232, 238-238


204-204: LGTM! Appropriate simplification of FrankenPHP options.

The removal of the logger option and retention of CPU-based thread configuration is a reasonable simplification.


455-514: LGTM! Inspect command properly migrated to ids package.

The migration of the inspect command from glue to ids package maintains the same functionality while aligning with the broader package refactor.


533-534: LGTM! New CLI options properly defined.

The addition of roles and claims options follows the established CLI patterns and provides appropriate configuration for enhanced user creation.

Signed-off-by: Robert Landers <landers.robert@gmail.com>
Signed-off-by: Robert Landers <landers.robert@gmail.com>
Signed-off-by: Robert Landers <landers.robert@gmail.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (6)
cli/lib/api.go (6)

357-382: Add missing return statements and fix success response.

Several error responses are missing return statements, and the success response incorrectly uses http.Error.

 r, err := rm.DiscoverResource(ctx, stateId, logger, true)
 if err != nil {
     logger.Error("Failed to discover resource", zap.Error(err))
     http.Error(writer, "Not Found", http.StatusNotFound)
+    return
 }

 newUser := strings.TrimSpace(vars["userid"])

 err = r.ShareOwnership(auth.UserId(newUser), auth.GetUserFromContext(ctx), true)
 if err != nil {
     logger.Error("Failed to share ownership", zap.Error(err))
     http.Error(writer, "Internal Server Error", http.StatusInternalServerError)
+    return
 }

 err = r.Update(ctx, logger)
 if err != nil {
     logger.Error("Failed to update resource", zap.Error(err))
     http.Error(writer, "Internal Server Error", http.StatusInternalServerError)
+    return
 }

 logger.Info("Shared ownership", zap.String("id", id.String()), zap.String("newUser", newUser))
-http.Error(writer, "", http.StatusOK)
+writer.WriteHeader(http.StatusOK)

433-460: Add missing return statements and error messages.

Missing return statements after error responses and empty error messages need to be fixed.

 r, err := rm.DiscoverResource(ctx, stateId, logger, true)
 if err != nil {
     logger.Error("Failed to discover resource", zap.Error(err))
-    http.Error(writer, "", http.StatusNotFound)
+    http.Error(writer, "Not Found", http.StatusNotFound)
+    return
 }

 switch vars["type"] {
 case "user":
     err = r.GrantUser(auth.UserId(vars["user"]), operation, ctx)
 case "role":
     err = r.GrantRole(auth.Role(vars["user"]), operation, ctx)
 }
 if err != nil {
     logger.Error("Failed to grant resource", zap.Error(err))
-    http.Error(writer, "", http.StatusForbidden)
+    http.Error(writer, "Forbidden", http.StatusForbidden)
+    return
 }

 err = r.Update(ctx, logger)
 if err != nil {
     logger.Error("Failed to update resource", zap.Error(err))
-    http.Error(writer, "", http.StatusInternalServerError)
+    http.Error(writer, "Internal Server Error", http.StatusInternalServerError)
+    return
 }

-http.Error(writer, "", http.StatusOK)
+writer.WriteHeader(http.StatusOK)

488-515: Fix missing return statements and error messages.

This handler has the same pattern of missing returns and empty error messages.

 r, err := rm.DiscoverResource(ctx, stateId, logger, true)
 if err != nil {
     logger.Error("Failed to discover resource", zap.Error(err))
-    http.Error(writer, "", http.StatusNotFound)
+    http.Error(writer, "Not Found", http.StatusNotFound)
+    return
 }

 switch vars["type"] {
 case "user":
     err = r.RevokeUser(auth.UserId(vars["user"]), ctx)
 case "role":
     err = r.RevokeRole(auth.Role(vars["user"]), ctx)
 }
 if err != nil {
     logger.Error("Failed to revoke resource", zap.Error(err))
-    http.Error(writer, "", http.StatusForbidden)
+    http.Error(writer, "Forbidden", http.StatusForbidden)
+    return
 }

 err = r.Update(ctx, logger)
 if err != nil {
     logger.Error("Failed to update resource", zap.Error(err))
-    http.Error(writer, "", http.StatusInternalServerError)
+    http.Error(writer, "Internal Server Error", http.StatusInternalServerError)
+    return
 }

-http.Error(writer, "", http.StatusOK)
+writer.WriteHeader(http.StatusOK)

685-710: Add missing return statements and fix success response.

Same pattern of missing returns as the entity share handler.

 r, err := rm.DiscoverResource(ctx, stateId, logger, true)
 if err != nil {
     logger.Error("Failed to discover resource", zap.Error(err))
     http.Error(writer, "Not Found", http.StatusNotFound)
+    return
 }

 newUser := strings.TrimSpace(vars["userid"])

 err = r.ShareOwnership(auth.UserId(newUser), auth.GetUserFromContext(ctx), true)
 if err != nil {
     logger.Error("Failed to share ownership", zap.Error(err))
     http.Error(writer, "Internal Server Error", http.StatusInternalServerError)
+    return
 }

 err = r.Update(ctx, logger)
 if err != nil {
     logger.Error("Failed to update resource", zap.Error(err))
     http.Error(writer, "Internal Server Error", http.StatusInternalServerError)
+    return
 }

 logger.Info("Shared ownership", zap.String("id", id.String()), zap.String("newUser", newUser))
-http.Error(writer, "", http.StatusOK)
+writer.WriteHeader(http.StatusOK)

761-788: Fix missing return statements and error messages.

Same issues as the entity grant handler.

 r, err := rm.DiscoverResource(ctx, stateId, logger, true)
 if err != nil {
     logger.Error("Failed to discover resource", zap.Error(err))
-    http.Error(writer, "", http.StatusNotFound)
+    http.Error(writer, "Not Found", http.StatusNotFound)
+    return
 }

 switch vars["type"] {
 case "user":
     err = r.GrantUser(auth.UserId(vars["user"]), operation, ctx)
 case "role":
     err = r.GrantRole(auth.Role(vars["user"]), operation, ctx)
 }
 if err != nil {
     logger.Error("Failed to grant resource", zap.Error(err))
-    http.Error(writer, "", http.StatusForbidden)
+    http.Error(writer, "Forbidden", http.StatusForbidden)
+    return
 }

 err = r.Update(ctx, logger)
 if err != nil {
     logger.Error("Failed to update resource", zap.Error(err))
-    http.Error(writer, "", http.StatusInternalServerError)
+    http.Error(writer, "Internal Server Error", http.StatusInternalServerError)
+    return
 }

-http.Error(writer, "", http.StatusOK)
+writer.WriteHeader(http.StatusOK)

816-843: Fix missing return statements and error messages.

Same issues as the entity revoke handler.

 r, err := rm.DiscoverResource(ctx, stateId, logger, true)
 if err != nil {
     logger.Error("Failed to discover resource", zap.Error(err))
-    http.Error(writer, "", http.StatusNotFound)
+    http.Error(writer, "Not Found", http.StatusNotFound)
+    return
 }

 switch vars["type"] {
 case "user":
     err = r.RevokeUser(auth.UserId(vars["user"]), ctx)
 case "role":
     err = r.RevokeRole(auth.Role(vars["user"]), ctx)
 }
 if err != nil {
     logger.Error("Failed to revoke resource", zap.Error(err))
-    http.Error(writer, "", http.StatusForbidden)
+    http.Error(writer, "Forbidden", http.StatusForbidden)
+    return
 }

 err = r.Update(ctx, logger)
 if err != nil {
     logger.Error("Failed to update resource", zap.Error(err))
-    http.Error(writer, "", http.StatusInternalServerError)
+    http.Error(writer, "Internal Server Error", http.StatusInternalServerError)
+    return
 }

-http.Error(writer, "", http.StatusOK)
+writer.WriteHeader(http.StatusOK)
🧹 Nitpick comments (1)
src/Proxy/SpyProxy.php (1)

101-125: Consider documenting why the $class parameter is unused.

The $class parameter appears to be unused but is likely required by the parent class contract. Consider adding a comment to clarify this for future maintainers.

 protected function preamble(ReflectionClass $class): string
 {
+    // $class parameter is required by parent contract but not used in this implementation
     return <<<'EOT'
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 87ae835 and 7d6977a.

📒 Files selected for processing (3)
  • Dockerfile (2 hunks)
  • cli/lib/api.go (17 hunks)
  • src/Proxy/SpyProxy.php (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • Dockerfile
🧰 Additional context used
🪛 PHPMD (2.15.0)
src/Proxy/SpyProxy.php

101-101: Avoid unused parameters such as '$class'. (Unused Code Rules)

(UnusedFormalParameter)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: build-docker
  • GitHub Check: build-osx (x86_64)
  • GitHub Check: build-osx (arm64)
  • GitHub Check: build-linux (amd64)
  • GitHub Check: build-linux (arm64)
  • GitHub Check: Unit Tests - PHP
🔇 Additional comments (1)
src/Proxy/SpyProxy.php (1)

33-36: Good fix for passing the $isHook parameter.

The implementation now correctly passes the $isHook parameter to impureCall, maintaining consistency with other proxy implementations.

Signed-off-by: Robert Landers <landers.robert@gmail.com>
Signed-off-by: Robert Landers <landers.robert@gmail.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🔭 Outside diff range comments (1)
cli/build.sh (1)

114-116: -race is passed via -ldflags; it has no effect there.

-race is a compile-time flag for go build, not a linker flag.
Because it is appended to extraLdflags and injected into -ldflags, race detection is never enabled.

-  extraLdflags="-w -s -race"
+  extraLdflags="-w -s"
+  raceFlag="-race"       # compile-time

Then include "$raceFlag" next to -buildmode in the go build invocation (mind that static PIE + race is unsupported on some platforms, so keep it conditional).

This guarantees that the data-race detector is really compiled in when expected.

🧹 Nitpick comments (1)
cli/build.sh (1)

118-120: go get durable_php is deprecated in Go 1.24; prefer go mod download or go install.

go get outside a module context is now a no-op and emits a warning.
If the intent is to pre-fetch module dependencies use:

go mod download

If the intent is to install a binary, use:

go install durable_php@latest

Adjusting this keeps the build script future-proof with recent Go tool-chain behaviour.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 000cd18 and 76ce211.

📒 Files selected for processing (1)
  • cli/build.sh (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: build-linux (arm64)
  • GitHub Check: build-docker
  • GitHub Check: build-linux (amd64)
  • GitHub Check: build-osx (arm64)
  • GitHub Check: Unit Tests - PHP

Signed-off-by: Robert Landers <landers.robert@gmail.com>
Signed-off-by: Robert Landers <landers.robert@gmail.com>
Signed-off-by: Robert Landers <landers.robert@gmail.com>
Signed-off-by: Robert Landers <landers.robert@gmail.com>
@codecov
Copy link

codecov bot commented Jul 30, 2025

Codecov Report

❌ Patch coverage is 42.05817% with 259 lines in your changes missing coverage. Please review.
✅ Project coverage is 46.26%. Comparing base (2c33885) to head (8e47c43).
⚠️ Report is 1 commits behind head on v2.

Files with missing lines Patch % Lines
src/RemoteEntityClient.php 0.00% 51 Missing ⚠️
src/EntityContext.php 0.00% 43 Missing ⚠️
src/RemoteOrchestrationClient.php 0.00% 40 Missing ⚠️
src/Proxy/SpyProxy.php 0.00% 25 Missing ⚠️
src/DurableClient.php 0.00% 20 Missing ⚠️
src/OrchestrationContext.php 56.75% 16 Missing ⚠️
src/State/EntityHistory.php 57.57% 14 Missing ⚠️
src/Glue/glue.php 0.00% 7 Missing ⚠️
src/Contexts/AuthContext/functions.php 0.00% 6 Missing ⚠️
src/Testing/DummyOrchestrationContext.php 66.66% 6 Missing ⚠️
... and 11 more
Additional details and impacted files
@@             Coverage Diff              @@
##                 v2     #141      +/-   ##
============================================
+ Coverage     45.00%   46.26%   +1.26%     
- Complexity     1166     1248      +82     
============================================
  Files            94       99       +5     
  Lines          3273     3562     +289     
============================================
+ Hits           1473     1648     +175     
- Misses         1800     1914     +114     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions
Copy link

Performance Metrics

test time (s) memory usage
perf 16.05 170
Fan out/in 60.07 8

@withinboredom withinboredom merged commit 808d9e5 into v2 Jul 30, 2025
5 of 6 checks passed
@withinboredom withinboredom deleted the withinboredom-patch-1 branch July 30, 2025 21:57
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