Skip to content

Let modules ship the third-party packages the host lacks - #13

Merged
gdarko merged 2 commits into
masterfrom
feat/bundled-dependencies
Oct 24, 2026
Merged

gdarko merged 2 commits into
masterfrom
feat/bundled-dependencies

Conversation

@gdarko

@gdarko gdarko commented Oct 24, 2026

Copy link
Copy Markdown
Contributor

Adds a second dependency policy, bundled (schema 2, module API 1.4), so a module can ship the third-party packages the host lacks.

  • invoiceshelf-module bundle resolves the module's packages against a host release's production composer.lock (host packages become root replace entries, so Composer reuses them and refuses a version the host does not ship), writes bundle/ with a relative classmap and bundle.json, and pins the result in a committed bundle.lock. Rebuilds are byte-identical.
  • Package validation checks bundle/ without running it: licenses, Composer plugins, reserved namespaces, declared extensions, symlinks, size, and that bundle.json matches the files.
  • host-provided-only validates exactly as before; Tasks and Projects 0.2.1 is kept as a regression fixture.
  • The release workflow takes a host-version input for bundled modules and ships bundle/ next to dist/. The SDK gets its own CI.

Tried against real packages: Stripe, Mollie, Braintree, Razorpay, PhpSpreadsheet, Twilio, Sentry, QuickBooks and the AWS SDK bundle; the PayPal server SDK is refused (OSL-3.0); the Google API client is over the archive limit.

Host side: InvoiceShelf feat/bundled-dependencies. Reference module: module-helloworld feat/bundled-dependencies. integration/3.5 merges this with feat/invoice-extension-slots for testing both and can go once 3.5.0 is tagged.

A new dependency_policy, bundled, lets a schema-2 module on module API 1.4
declare third-party packages in composer.json. invoiceshelf-module bundle
resolves them against a host release's production composer.lock, with every
host package as a root replace at its locked version, so Composer reuses what
the host ships, installs only what it lacks and refuses a version the host
does not have. The command writes bundle/ itself (package files, a relative
classmap the host reads as data, and bundle.json recording versions,
licenses, host constraints per requirer, files entries and the functions
they declare) and pins the result in a committed bundle.lock. The same lock
writes the same bytes on every machine.

Package validation checks bundle/ without running any of it and refuses
incompatible licenses, Composer plugins, reserved namespaces, undeclared
extensions, symlinks and stale metadata. host-provided-only modules validate
exactly as before; Tasks and Projects 0.2.1 is kept as a regression fixture.

The release workflow takes a host-version input for bundled modules, builds
from the committed lock against that release, pins Composer and ships bundle/
next to dist/. The SDK gains its own CI.
@gdarko
gdarko marked this pull request as ready for review October 24, 2026 00:38
@gdarko
gdarko merged commit 9f8f7ef into master Oct 24, 2026
2 checks passed
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.

1 participant