Repository navigation
refactor(plugins): delete the retired first-party plugin block and restore upstream's plugin schema - #248
Merged
Conversation
…ata and its schema The read-only "retired first-party plugins" block of the admin Plugins page is deleted as a whole: the panel, the seven retired installation rows and the retirement receipt. Upstream's plugin management is back in its v0.2.13 form. Backend - the startup step that retired first-party installations (service and repository), the repository wrapper that hid the seven keys from the plugin manager, GET /admin/plugins/retired and their tests are deleted; - the wiring is upstream's again: repository.NewPluginRepository and admin.NewPluginHandler. ProvideSettingService loses the parameter that only ordered it after the retirement; wire_gen.go is regenerated; - plugin_handler.go is byte-identical to v0.2.13. Three response headers that served the first-party plugin UIs go with it: Cache-Control on the two configuration interfaces (4129f63, the versioned management view), Access-Control-Allow-Origin on plugin UI assets (387b0a7, the prompt management UI) and worker-src blob: in their CSP (8a4d280, the account import UI). Migration 272 - deletes the seven first-party installations with their bindings and the receipt, and drops the schema only they used (sub2api_plugin_bootstrap, sub2api_plugin_updates, four columns, the state 'updating', the revision trigger and function, the narrowed unique index), so both plugin tables are as upstream's 229 and 230 define them; - raises, changing nothing, on a first-party installation the receipt does not record as retired, on another installation in the state 'updating' and on two enabled bindings of one scope; - has no down path: every earlier release since v0.2.8-codexrip.5 reads the dropped column runtime_generation at start and exits; - 264 is released and names the dropped objects, so its test puts 248, 249 and 250 back before each case. Frontend - RetiredPluginsPanel.vue, its API function and types, its i18n keys and its CSS rules are deleted; - api/admin/plugins.ts, both admin/plugins.ts locales and PluginsView.spec.ts are byte-identical to v0.2.13; PluginsView.vue keeps only the console theme hook data-ui="plugins"; - the rawPluginConfig bypass of the response interceptor (4129f63) and the "plugin unavailable" line of the re-authorization dialog (cd8c18b), which no longer had a reason, are removed. CI and docs - test_native_domains.sh no longer selects the deleted tests or ./internal/repository, where it would select nothing; downstream-verify.yml drops the retirement selector; - .downstream/native-domains.md states what 272 removes, what it leaves and the rollback boundary. Not in the database and left for the operator: the Redis keys plugin:kv:v1:codexrip.* and the plugin files under <data dir>/plugins. The deploy workflow, the release workflow and deploy/ are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… first-party plugins left in live code Review of the retired-plugin removal found files of upstream's plugin system that were still in their first-party form, and plugin-era code that survived under other names. Upstream form restored, byte for byte - pkg/pluginapi/v1/manifest.schema.json and runtime.go. The schema advertised ten extensions.*.v1 capabilities and five manifest fields the host rejects; runtime.go carried a Connection field and an AdditionalServiceRegistrar hook nothing used. - pkg/proxyutil/dialer.go. internal/proxytransport, which existed to be shared with plugin processes and had this one caller, is deleted. No caller passes a transport with Proxy set, so the SOCKS branch behaves as before. - provideCleanup stops the plugin manager as a parallel step again instead of after all of them; wire_gen.go is regenerated. The account job runtime keeps its own step. - modelsListCacheKey and InvalidateAvailableModelsCache. Cache keys have had two parts since the provider namespace went, so the three-part matching selected nothing more than upstream's does. - the /plugins/ comments of .dockerignore and .gitignore. Deleted - service/testdata/plugin_contribution_buckets.json, which no test read; - the .dockerignore exception for deploy/plugin-bundle/README.md, which no Dockerfile copies. Comments and DOWNSTREAM.md no longer explain current code by the plugin configuration or packaging that preceded it. deploy/plugin-bundle/README.md is left: deploy/ is outside this change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Migration 272 gave one remedy, "start v0.2.13-codexrip.7 once", for three different states of the retirement receipt. An earlier release retires an installation only while no receipt is stored: on a receipt that is not completed it exits at start, and once a completed one is stored it retires nothing. - A stored receipt that does not cover an installed first-party plugin now raises its own message: no release repairs it and it is resolved by hand. The message for a missing receipt is unchanged in substance. Both, and the two for other installations, name v0.2.13-codexrip.8, the last release before these migrations, and point to .downstream/native-domains.md. - The document says what such a refusal leaves behind. Each migration commits on its own, so 270 and 271 are applied by then; v0.2.13-codexrip.8 needs Image Studio off and usage_billing_dedup.account_id added back on that database. The previous commit had removed both facts. - It names what the seven plugins stored outside the database (package files, unpacked trees, Redis keys with the codexrip. prefix) instead of everything under the plugin directory, and says they are deleted by hand at the release that applies 272. The files of other plugins stay. - It no longer describes the deleted startup retirement by negation. Test: the three cases of an uncovered installation expect the two messages. The assertions that a refused migration changes nothing ran after a rollback to a savepoint and could not fail; they are removed, since the runner's one transaction per file is what guarantees it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…aises The test of 264 held the pattern the test of 272 took over: after the refused migration it rolled back to a savepoint and then asserted that nothing had changed, which holds for any migration. The assertions are removed. That a file which raises changes nothing follows from the runner's one transaction per file. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The refusal messages of 272 cannot change once the migration is released. They named .downstream/native-domains.md, a file whose name comes from the plugin era and is due to change. DOWNSTREAM.md links to the same text and keeps its name. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The admin Plugins page ends with a read-only block, "retired first-party plugins": seven cards and a retirement receipt. Nothing in it can be acted on. Behind it the fork keeps a startup step that retires first-party plugin installations, a wrapper that hides their rows from upstream's plugin manager, and schema only those plugins used. The owner decided the block goes as a whole, with its stored data.
Change
Backend: upstream's plugin wiring
service/native_feature_bootstrap.go,repository/native_feature_bootstrap.go), the repository wrapper (repository/native_plugin_boundary.go),GET /admin/plugins/retired, and their tests.repository.NewPluginRepositoryandadmin.NewPluginHandler(manager)are wired directly, as upstream does.ProvideSettingServiceloses the parameter it took only for ordering.handler/admin/plugin_handler.go,pkg/pluginapi/v1/manifest.schema.json,pkg/pluginapi/v1/runtime.go,internal/pkg/proxyutil/dialer.go(the fork-onlyproxytransportpackage is gone).registerPluginRoutesand the plugin manager's place in shutdown match upstream.Cache-Control: private, no-storeon plugin config,Access-Control-Allow-Origin: *andworker-src blob:on plugin UI assets), an orphan testdata file, and comments describing deleted plugin structure.Migration
272_purge_first_party_plugins.sqlsettings.deplugin_retired_plugins.sub2api_plugin_bootstrapandsub2api_plugin_updates, the columnsrevision,runtime_generation,package_sha256,update_policy, the stateupdating, the trigger and functionsub2api_plugin_revision, and the narrowed unique index on enabled bindings.sub2api_plugin_installationsandsub2api_plugin_bindingsare then as 229 and 230 define them.updating, or when two enabled bindings share a scope. Each message names what resolves it.settings.admin_observability_configare not written.Frontend: upstream's Plugins page
RetiredPluginsPanel.vue, its API functions and types, its i18n keys and CSS,rawPluginConfigin the API client, and the "plugin unavailable" line in the re-auth dialog that could never show.api/admin/plugins.ts, bothi18n/locales/*/admin/plugins.tsandPluginsView.spec.tsare byte-identical to v0.2.13.PluginsView.vuediffers only by the theme hookdata-ui="plugins".Migration 264's test recreates the objects 264 needs before running it; 264 itself is released and unchanged.
What an admin sees
Rollback boundary
There is no down path. An image older than this release finds no receipt at start, runs the retirement query, reads the dropped column
runtime_generationand exits..downstream/native-domains.mdhas the details, including what an older image needs if 272 refuses after 270 and 271 have committed.Outside the database
The seven plugins' package files, unpacked trees and any Redis key
plugin:kv:v1:codexrip.*are removed once on the server at the release that applies 272. Production is checked read-only against 272's three refusal conditions before that release.Verification
go build ./...(default andGOOS=linux);go vet ./...with no tag,-tags unit, and-tags integrationon repository;wire diffclean; gofmt.TestMigration272PurgesFirstPartyPlugins(8 cases) andTestMigration264PurgesCodexRuntimePluginData(12 cases) on a throwaway PostgreSQL 18 from an empty database; 272 also applied by hand to a production-shaped database.vue-tsc,check:i18n, the PluginsView spec; the changed CI selector with its contract test.-codexrip.Nsuffix as a pre-release.Not run locally: golangci-lint (the local binary cannot read Go 1.27 export data), the full unit and integration suites, frontend eslint and full vitest, real model calls. CI runs the required ones.
🤖 Generated with Claude Code