Skip to content

feat(flutter): document the Flutter SDK and publish it to pub.dev (#199) - #222

Draft
V3RON wants to merge 8 commits into
mainfrom
issue-199-document-the-flutter-sdk-and-publish-it-to-pub-dev
Draft

V3RON wants to merge 8 commits into
mainfrom
issue-199-document-the-flutter-sdk-and-publish-it-to-pub-dev

Conversation

@V3RON

@V3RON V3RON commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Requested by Szymon · project thread

Closes #199 (slice 9 of 9 of #189)

Before the first release (a human must do this)

Nothing is published from this PR. deploy.yaml starts publish-pub.yaml at the release tag after the npm publishes; that run fails, and publishes nothing, until a maintainer has:

  1. Claimed the package name on pub.dev by publishing appduct once by hand (or the fallback appduct_flutter; if so, change name: in packages/flutter/pubspec.yaml and the flutter pub add lines in the docs). Publish from a clean checkout: .pubignore now excludes build output, but check the dry-run size (about 75 KB).
  2. Enabled automated publishing on the package's Admin tab: GitHub Actions, repository callstackincubator/appduct, tag pattern v{{version}}, require the GitHub environment pub.dev, and tick "enable publishing from workflow_dispatch events".
  3. Created the pub.dev environment under the repository's Settings > Environments (no secrets needed).

pub.dev refuses a version that already exists, so the first release cut after this PR must be higher than whatever was published by hand.

Why workflow_dispatch and not a tag push. pub.dev accepts OIDC tokens only from push and workflow_dispatch events, never release. A dispatch can be started with GITHUB_TOKEN (actions: write on one small job), while a tag created by a release made with GITHUB_TOKEN does not start push workflows. It also gives a retry button (run the workflow on the tag) and keeps the pub job out of the npm release: nothing needs start-pub-publish, so a pub.dev failure never fails deploy.yaml.

What changed

The Flutter package is documented and publishable. It has a README, a CHANGELOG, an example and pub.dev metadata, and publish_to: none is gone (dart pub publish --dry-run reports 0 warnings and runs in the Flutter CI job). The package is versioned in lockstep with the npm packages: scripts/release-version.mjs fails when pubspec.yaml, the podspec, the Gradle version and the three package.json files differ, and deploy.yaml runs it against the release tag. The cut-release skill bumps all of them. The website has a Flutter setup page; build variants, security, introduction, quick start, the README, the package READMEs and the shipped skill cover Flutter.

Docs findings covered: B3 and C5 (opt-in release build, INTERNET, iOS local network key, macOS network.client), B5 (APPDUCT_PINS, APPDUCT_TRUST, APPDUCT_ALLOW_PRIVATE_LAN_ONLY through --dart-define-from-file), C4 (Isolate.run), T1 (num), the handler error-zone note from #216, desktop connect(link) and APPDUCT_LINK.

Acceptance criteria

# Criterion Test Tier
1 dart pub publish --dry-run passes in CI New step in the flutter job of test.yaml; 0 warnings locally CI
2 The pub step shows the package would be published at the release version release-version.e2e.test.ts (versions agree, tag must be v<version>, prerelease refused); publish-pub.yaml prints the dry run at $PUB_VERSION e2e
6 The pub archive leaves out build output flutter-pubignore.test.ts (.pubignore covers .gitignore); CI fails if the dry run lists build/ or .dart_tool/ or exceeds 1 MB unit, CI
7 pub.dev lists Windows and Linux desktop_plugin_test.dart (Dart-only plugin class; the binding still owns Appduct with no shim) unit
3 The website builds with the Flutter page; the skill has a Flutter section pnpm --filter website build (link validator), pnpm check:links build
4 B3, B5, C4, C5, T1 are in the docs website/src/content/docs/install/flutter.mdx, guides/build-variants.mdx, guides/security.mdx, skills/appduct/references/setup.md review
5 The cut-release skill bumps pubspec.yaml with the rest release-version.e2e.test.ts "holds for this repository"; skill updated e2e

E2E evidence

not applicable (docs, CI and release tooling; no device behaviour changed)

Checklist

  • CHANGELOG.md has an entry under Unreleased (writing-changelog skill), including the release-build default asked for in Document the Flutter SDK and publish it to pub.dev #199
  • User-facing docs updated for every surface the change touches (writing-user-docs skill)
  • No new import past a module's index.ts; no new direct node:* I/O outside an adapter (the script is a build tool, not a module)
  • Simplification checklist from the architecture skill applied
  • docs/ARCHITECTURE.md updated if a surface it describes changed (not needed)

Out of scope

Status

Implement: done Review: round 2, approve E2E: not applicable Ready: held until the pub.dev name is claimed (merging deploys the website docs)

🤖 Generated with Claude Code

https://claude.ai/code/session_01R8SdLnR6fDS751JnAvzaSE


Generated by Claude Code

claude added 3 commits October 8, 2026 13:03
Release version check: 6 failing, 2 passing for the wrong reason

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R8SdLnR6fDS751JnAvzaSE
…#199)

Release version check: 1 failing -> 0 failing

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R8SdLnR6fDS751JnAvzaSE
…pub.dev publish job (#199)

1 failing -> 0 failing

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R8SdLnR6fDS751JnAvzaSE

@V3RON V3RON left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Request changes (posted as a comment): 2 blockers, 2 should-fix. Spec: #199 with its comments and the #189 design comment.
Fix first: publish-pub runs on the release event, which pub.dev refuses for OIDC publishing, so the Flutter package can never publish.


Generated by Claude Code

Comment thread .github/workflows/deploy.yaml Outdated
echo "::error::Timed out waiting for deployment $DEPLOYMENT_ID to validate. Re-running this job resumes watching it rather than uploading again."
exit 1

publish-pub:

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Blocker. pub.dev will refuse every publish from this job, even after the maintainer setup. The workflow runs on release, so the OIDC token's event_name is release, and pub.dev only accepts tokens from push or workflow_dispatch events. Its server rejects anything else with "publishing is only allowed from "push" or "workflow_dispatch" events, this token originates from a "release" event" (app/lib/package/backend.dart in dart-lang/pub-dev). So every release ends with this job failing and nothing on pub.dev, which fails P5 and issue criterion 2.

Fix: move the publish into its own on: workflow_dispatch workflow. After the npm jobs, deploy.yaml starts it at the release tag (gh workflow run ... --ref "$RELEASE_TAG" with actions: write). Then add "enable publishing from workflow_dispatch events" to the PR's maintainer steps and to the cut-release skill.


Generated by Claude Code

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 2b67353. The publish is now .github/workflows/publish-pub.yaml (workflow_dispatch, tag refs only). deploy.yaml has a start-pub-publish job with actions: write that runs gh workflow run publish-pub.yaml --ref $RELEASE_TAG after the npm jobs; nothing depends on it, so the npm release is independent. The PR body and the cut-release skill now say to enable publishing from workflow_dispatch events. I could not open dart.dev from this sandbox, so this relies on the server rule you quoted.


Generated by Claude Code

- Set `APPDUCT_LINK` when you start the app in debug mode:

```bash
APPDUCT_LINK="$(appduct sessions link --scheme myapp)" flutter run -d linux

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Blocker. This command never connects. Without --json, appduct sessions link prints its human block (Link Created, Session, Deep link, Endpoint, Pin, Expires, with ANSI colour codes), and $(...) captures all of it. I ran it: APPDUCT_LINK starts with \e[32mLink Created. The Dart side passes that string to handleUrl, which doesn't parse it as a link and drops it silently. The app starts and stays idle. This is the only path the page gives for Windows and Linux, and skills/appduct/references/setup.md:131 gives agents the same command.

Fix: in both places, use APPDUCT_LINK="$(appduct sessions link --scheme myapp --json | jq -r .data.deepLink)", or tell the reader to copy the Deep link value.


Generated by Claude Code

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 2b67353. Both places now use --json | jq -r .data.deepLink. I ran appduct sessions link --scheme myapp --json against a local daemon: the output is {"ok":true,"data":{"deepLink":"myapp:///?appduct=..."}}, and the jq form prints just the link. The page notes that jq is needed.


Generated by Claude Code

@@ -0,0 +1,4 @@
# Native unit-test harnesses; they are not part of the plugin.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Should-fix. When a directory has a .pubignore, pub ignores that directory's .gitignore. So /build/, .flutter-plugins-dependencies and the rest of packages/flutter/.gitignore are no longer excluded. I ran flutter test, then dart pub publish --dry-run: the archive includes build/ (unit_test_assets, test_cache, native_assets) and grows from 74 KB to 22 MB, with 0 warnings, so the CI dry run doesn't catch it. The PR tells a maintainer to claim the name by publishing by hand. Doing that from a tree where they've run the tests ships this permanently, because pub.dev versions can't be deleted.

Fix: copy the four packages/flutter/.gitignore entries into .pubignore.


Generated by Claude Code

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 2b67353. .pubignore now carries every .gitignore entry, and flutter-pubignore.test.ts fails if they drift. The CI dry-run step runs after flutter test and fails if the archive lists build/ or .dart_tool/ or reports a size in MB. After flutter test the archive is 74 KB again.


Generated by Claude Code


Call functions inside your running Flutter app from a terminal, a test runner or an AI agent. You register a few functions, called tools, with a name, a description and an input schema. The `appduct` CLI and its MCP server list and call them over an encrypted connection. Only the tools you register are reachable.

Works on Android, iOS, macOS, Windows and Linux. Flutter web isn't supported.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Should-fix. pub.dev will list the package as Android, iOS and macOS only. flutter.plugin.platforms in pubspec.yaml declares no windows or linux entry. pana on this head reports "Supports 3 of 6 possible platforms (iOS, Android, macOS)" and "package:appduct/appduct.dart declares support for platforms: Android, iOS, macOS". Windows and Linux developers who filter pub.dev by platform won't find the package, and the listing contradicts this line, the setup page and the changelog entry.

Fix: declare windows: and linux: under flutter.plugin.platforms with a dartPluginClass whose registerWith does nothing.


Generated by Claude Code

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 2b67353. windows: and linux: are declared with dartPluginClass: AppductDesktopPlugin (a no-op registerWith). The shim channel still has no handler there, so the binding falls back to owner with the file lease; desktop_plugin_test.dart covers it. I could not run pana here.


Generated by Claude Code

claude added 3 commits October 8, 2026 14:03
…inux (#199)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R8SdLnR6fDS751JnAvzaSE
…x platforms (#199)

2 failing -> 0 failing

- publish-pub.yaml runs on workflow_dispatch, started by deploy.yaml at the release tag
- .pubignore carries the .gitignore entries; CI fails if build/ or .dart_tool/ is archived
- windows and linux declared with a Dart-only plugin class
- sessions link examples use --json | jq -r .data.deepLink

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R8SdLnR6fDS751JnAvzaSE
… it (#199)

The host-app builds in CI failed; Flutter's generated registrant imports package:appduct/appduct.dart and ignores fileName.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R8SdLnR6fDS751JnAvzaSE

@V3RON V3RON left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Approve (posted as a comment): 0 blockers, 0 should-fix, 1 nit. Spec: #199 with its comments, plus the round-1 findings.
All four round-1 findings are fixed on 98f28eb and CI is green. The one thing left, optional: keep the desktop plugin class out of the public API (inline).


Generated by Claude Code

Comment thread packages/flutter/lib/appduct.dart Outdated
claude added 2 commits October 8, 2026 18:28
#199)

Declare dartFileName in pubspec.yaml so Flutter finds the Windows and
Linux plugin class without a public export.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R8SdLnR6fDS751JnAvzaSE
…e-flutter-sdk-and-publish-it-to-pub-dev

# Conflicts:
#	CHANGELOG.md

This branch has not been deployed

No deployments
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.

Document the Flutter SDK and publish it to pub.dev

2 participants