-
Notifications
You must be signed in to change notification settings - Fork 3
Bugfix/90 fix app install #91
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
3190b32
Add MCP server configuration and documentation: introduce `.mcp.json`…
mesilov 0c207e9
Update developer documentation for onboarding and AI/CLI tooling: add…
mesilov 83ad55a
Refactor `Install` and `OnAppInstall` use cases to support single-ste…
mesilov dde3b53
Refactor `Install` and `OnAppInstall` use cases: fix premature status…
mesilov 13fe39a
Refactor `Install` and `OnAppInstall` use cases: fix `new`-status han…
mesilov 1555d04
Refactor `Install` and `OnAppInstall` use cases: enhance `new`-status…
mesilov 573985a
Refactor `Install` and `OnAppInstall` use cases: consolidate updated …
mesilov e5b52d3
Refactor tests and helpers for `Install` and `OnAppInstall` use cases…
mesilov File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| { | ||
| "mcpServers": { | ||
| "bitrix24-dev": { | ||
| "type": "http", | ||
| "url": "https://mcp-dev.bitrix24.tech/mcp" | ||
| } | ||
| } | ||
| } | ||
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| # AGENTS | ||
|
|
||
| ## MCP Servers | ||
|
|
||
| This repository includes project-level MCP server configuration in `.mcp.json`. | ||
|
|
||
| Developers and agents working with this project must verify the MCP configuration before starting work. | ||
|
|
||
| Configured servers: | ||
|
|
||
| - `bitrix24-dev` - HTTP MCP server at `https://mcp-dev.bitrix24.tech/mcp` | ||
|
|
||
| Checks before work starts: | ||
|
|
||
| - ensure `.mcp.json` is present and contains the expected server list | ||
| - restart the client after pulling changes to `.mcp.json` | ||
| - verify that the configured MCP servers are available in the current client | ||
|
|
||
| ## Tests And Linters | ||
|
|
||
| Agents working in this repository must run linters and tests only through `Makefile` entrypoints. | ||
|
|
||
| Do not call tool binaries directly when an equivalent `make` target exists. | ||
|
|
||
| Use: | ||
|
|
||
| - `make lint-all` for the full linter pass | ||
| - `make test-unit` for the unit test suite | ||
| - `make test-functional` for the functional test suite | ||
| - `make lint-cs-fixer-fix` and `make lint-rector-fix` only when an autofix pass is needed |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,10 @@ | ||
| ## Unreleased | ||
| ## Unreleased 0.5.0 | ||
|
|
||
| ### Fixed | ||
| - Fix start state for Bitrix24 ApplicationAccounts and ApplicationInstall [#90](https://github.com/mesilov/bitrix24-php-lib/issues/90) | ||
|
|
||
|
|
||
|
|
||
|
Comment on lines
+5
to
+7
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
|
||
| ## 0.4.0 | ||
|
|
||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
179 changes: 179 additions & 0 deletions
179
src/ApplicationInstallations/Docs/application-installations.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,179 @@ | ||
| # ApplicationInstallations Install Flow | ||
|
|
||
| ## Overview | ||
|
|
||
| `ApplicationInstallations` stores the installation state for a Bitrix24 portal and coordinates it with the master `Bitrix24Account`. | ||
|
|
||
| The install flow is intentionally split into two contracts: | ||
|
|
||
| - `US1`: one-step install when the initial `Install` command already contains `applicationToken` | ||
| - `US2`: two-step install when `Install` starts the flow in `new`, and `OnAppInstall` performs the canonical finish-step | ||
|
|
||
| External references: | ||
|
|
||
| - SDK contract: https://github.com/bitrix24/b24phpsdk/blob/v3/src/Application/Contracts/ApplicationInstallations/Docs/ApplicationInstallations.md | ||
| - Bitrix24 `ONAPPINSTALL`: https://apidocs.bitrix24.com/api-reference/common/events/on-app-install.html | ||
| - Bitrix24 install finish behavior: https://apidocs.bitrix24.ru/api-reference/app-installation/installation-finish.html | ||
|
|
||
| ## US1: Install With Token | ||
|
|
||
| If `Install\Command::$applicationToken !== null`, `src/ApplicationInstallations/UseCase/Install/Handler.php` finishes the installation in one step: | ||
|
|
||
| 1. Create master `Bitrix24Account` in `new` | ||
| 2. Create `ApplicationInstallation` in `new` | ||
| 3. Call `Bitrix24Account::applicationInstalled($applicationToken)` | ||
| 4. Call `ApplicationInstallation::applicationInstalled($applicationToken)` | ||
| 5. Persist both aggregates and flush once | ||
|
|
||
| Result: | ||
|
|
||
| - both aggregates become `active` | ||
| - application token is stored immediately | ||
| - finish events are emitted on `Install` | ||
|
|
||
| ```mermaid | ||
| sequenceDiagram | ||
| autonumber | ||
| actor Caller as Installer | ||
| participant Install as Install Handler | ||
| participant Account as Bitrix24Account | ||
| participant Installation as ApplicationInstallation | ||
| participant Flusher as Flusher | ||
|
|
||
| Caller->>Install: handle(command with applicationToken) | ||
| Install->>Account: create(status=new) | ||
| Install->>Installation: create(status=new) | ||
| Install->>Account: applicationInstalled(token) | ||
| Install->>Installation: applicationInstalled(token) | ||
| Install->>Flusher: flush(installation, account) | ||
| ``` | ||
|
|
||
| ## US2: Install Without Token | ||
|
|
||
| If `Install\Command::$applicationToken === null`, `Install` only starts the installation: | ||
|
|
||
| 1. Create master `Bitrix24Account` in `new` | ||
| 2. Create `ApplicationInstallation` in `new` | ||
| 3. Persist both aggregates and flush once | ||
| 4. Do not call `applicationInstalled(...)` | ||
|
|
||
| Result: | ||
|
|
||
| - both aggregates stay in `new` | ||
| - token is still unknown | ||
| - finish events are not emitted on `Install` | ||
|
|
||
| The finish-step must then happen only in `src/ApplicationInstallations/UseCase/OnAppInstall/Handler.php`. | ||
|
|
||
| ```mermaid | ||
| sequenceDiagram | ||
| autonumber | ||
| actor Caller as Installer | ||
| participant Install as Install Handler | ||
| participant Account as Bitrix24Account | ||
| participant Installation as ApplicationInstallation | ||
| participant Flusher as Flusher | ||
|
|
||
| Caller->>Install: handle(command without applicationToken) | ||
| Install->>Account: create(status=new) | ||
| Install->>Installation: create(status=new) | ||
| Install->>Flusher: flush(installation, account) | ||
| ``` | ||
|
|
||
| ## Canonical Finish-Step | ||
|
|
||
| `OnAppInstall` is the canonical finish-step for the two-step install flow. | ||
|
|
||
| Algorithm: | ||
|
|
||
| 1. Load current non-deleted installation by `memberId` | ||
| 2. If installation is `new`: | ||
| - load master `Bitrix24Account` by `memberId` only in status `new` | ||
| - call `changeApplicationStatus(...)` | ||
| - call `Bitrix24Account::applicationInstalled($applicationToken)` | ||
| - call `ApplicationInstallation::applicationInstalled($applicationToken)` | ||
| - persist both aggregates and flush once | ||
| 3. If installation is already `active`: | ||
| - load master `Bitrix24Account` by `memberId` only in status `active` | ||
| - log warning and return `no-op` | ||
| 4. Otherwise: | ||
| - throw a controlled exception | ||
|
|
||
| `Bitrix24Accounts\UseCase\InstallFinish\Handler` remains an account-only use case and is not the canonical finish path for `ApplicationInstallations`. | ||
|
|
||
| ```mermaid | ||
| sequenceDiagram | ||
| autonumber | ||
| actor B24 as Bitrix24 ONAPPINSTALL | ||
| participant Handler as OnAppInstall Handler | ||
| participant Repo as Installation Repository | ||
| participant AccountRepo as Account Repository | ||
| participant Account as Bitrix24Account | ||
| participant Installation as ApplicationInstallation | ||
| participant Flusher as Flusher | ||
|
|
||
| B24->>Handler: handle(memberId, applicationToken, applicationStatus) | ||
| Handler->>Repo: findByBitrix24AccountMemberId(memberId) | ||
| alt pending installation in status new | ||
| Handler->>AccountRepo: findByMemberId(memberId, status=new) | ||
| Handler->>Installation: changeApplicationStatus(status) | ||
| Handler->>Account: applicationInstalled(token) | ||
| Handler->>Installation: applicationInstalled(token) | ||
| Handler->>Flusher: flush(installation, account) | ||
| else already active installation | ||
| Handler->>AccountRepo: findByMemberId(memberId, status=active) | ||
| Handler-->>B24: warning + no-op | ||
| else no pending installation | ||
| Handler-->>B24: controlled exception | ||
| end | ||
| ``` | ||
|
|
||
| ## Corner Cases | ||
|
|
||
| - Duplicate `ONAPPINSTALL` with the same token: | ||
| `OnAppInstall` does not mutate state, does not emit events, and writes a warning log entry. | ||
| - Repeated `ONAPPINSTALL` with a different token: | ||
| `OnAppInstall` still does not mutate state, does not emit events, and writes a warning log entry. | ||
| - Missing pending installation: | ||
| `OnAppInstall` throws `ApplicationInstallationNotFoundException`. | ||
| - Pending installation exists but master account in status `new` is missing: | ||
| `OnAppInstall` throws `Bitrix24AccountNotFoundException`. | ||
| - Reinstall over pending installation: | ||
| `Install` moves the previous installation through `markAsBlocked('reinstall before finish') -> applicationUninstalled(null)`, deletes related accounts, flushes deletions, and only then creates a new pair. | ||
| - Reinstall over active installation: | ||
| previous non-deleted aggregates are moved to `deleted`, then a new pair is created. | ||
|
|
||
| ## Reinstall Before Finish | ||
|
|
||
| ```mermaid | ||
| sequenceDiagram | ||
| autonumber | ||
| actor Caller as Installer | ||
| participant Install as Install Handler | ||
| participant OldInstallation as Old Installation | ||
| participant OldAccount as Old Master Account | ||
| participant Flusher as Flusher | ||
| participant NewAccount as New Account | ||
| participant NewInstallation as New Installation | ||
|
|
||
| Caller->>Install: handle(new Install command) | ||
| Install->>OldInstallation: markAsBlocked('reinstall before finish') | ||
| Install->>OldInstallation: applicationUninstalled(null) | ||
| Install->>OldAccount: applicationUninstalled(null) | ||
| Install->>Flusher: flush(old installation, old account...) | ||
| Install->>NewAccount: create(status=new or active by token) | ||
| Install->>NewInstallation: create(status=new or active by token) | ||
| Install->>Flusher: flush(new installation, new account) | ||
| ``` | ||
|
|
||
| ## Follow-Up | ||
|
|
||
| Stale `new` installations remain possible when Bitrix24 never delivers the finish-step. This library does not auto-heal them synchronously. | ||
|
|
||
| The follow-up issue tracks background cleanup options such as: | ||
|
|
||
| - GitHub issue: https://github.com/mesilov/bitrix24-php-lib/issues/92 | ||
| - TTL worker that marks stale `new` installations as failed | ||
| - TTL worker with alert-only behavior | ||
| - reconciliation job for portal state re-check | ||
| - manual operational recovery flow |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a good practice for files to end with a newline character. This can prevent issues with some command-line tools and file processing scripts. I've added one to the file.