openui-rails 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/AUDIT.md +24 -4
  3. data/CHANGELOG.md +52 -1
  4. data/CONFIGURATION.md +9 -77
  5. data/CONTRIBUTING.md +29 -1
  6. data/DEVELOPMENT.md +89 -0
  7. data/README.md +50 -439
  8. data/RELEASING.md +30 -8
  9. data/THIRD_PARTY_NOTICES.md +10 -0
  10. data/UPGRADING.md +7 -24
  11. data/app/javascript/openui/rails/openui_controller.js +14 -1
  12. data/examples/support_desk/README.md +18 -0
  13. data/examples/support_desk/app/controllers/support_desk/base_controller.rb +37 -0
  14. data/examples/support_desk/app/controllers/support_desk/conversations_controller.rb +47 -0
  15. data/examples/support_desk/app/controllers/support_desk/sessions_controller.rb +19 -0
  16. data/examples/support_desk/app/javascript/support_desk.js +109 -0
  17. data/examples/support_desk/app/models/support_desk/conversation.rb +108 -0
  18. data/examples/support_desk/app/models/support_desk/demo.rb +15 -0
  19. data/examples/support_desk/app/models/support_desk/receipt.rb +6 -0
  20. data/examples/support_desk/app/models/support_desk/ticket.rb +6 -0
  21. data/examples/support_desk/app/models/support_desk/user.rb +6 -0
  22. data/examples/support_desk/app/views/layouts/support_desk/application.html.erb +18 -0
  23. data/examples/support_desk/app/views/support_desk/conversations/index.html.erb +6 -0
  24. data/examples/support_desk/app/views/support_desk/conversations/show.html.erb +16 -0
  25. data/examples/support_desk/boot.rb +21 -0
  26. data/examples/support_desk/config/importmap.rb +4 -0
  27. data/examples/support_desk/config/initializers/openui.rb +32 -0
  28. data/examples/support_desk/config/routes.rb +12 -0
  29. data/examples/support_desk/db/migrate/20261019000000_create_support_desk.rb +33 -0
  30. data/examples/support_desk/install.rb +15 -0
  31. data/lib/generators/openui/install/install_generator.rb +6 -5
  32. data/lib/generators/openui/install/templates/config/initializers/openui.rb.tt +2 -2
  33. data/lib/generators/openui/install/templates/config/openui/README.md +19 -4
  34. data/lib/openui/rails/default_library/library.prompt.txt +198 -0
  35. data/lib/openui/rails/default_library/library.spec.json +4390 -0
  36. data/lib/openui/rails/default_library/openui.LICENSE.txt +21 -0
  37. data/lib/openui/rails/default_library/provenance.json +15 -0
  38. data/lib/openui/rails/default_library.rb +85 -0
  39. data/lib/openui/rails/doctor.rb +143 -0
  40. data/lib/openui/rails/library_manifest.rb +2 -1
  41. data/lib/openui/rails/surface.rb +22 -4
  42. data/lib/openui/rails/version.rb +1 -1
  43. data/lib/openui/rails.rb +2 -0
  44. data/lib/tasks/openui.rake +19 -0
  45. metadata +28 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f5365a84ab993b7d1d7efd392753a9699f28cbe17acd8482d517e0e529150a6c
4
- data.tar.gz: d071e4fbd4f29fefd7a074f411b30cdd0b453bc5532410bbcb7af3333184f340
3
+ metadata.gz: 3d3b9295fd6e8fb6d3b284c0c66d80e3d02f01e7d1c09913f02acfd6ff183273
4
+ data.tar.gz: 9e5eb58014af64320ea178b05f63843f617f5fe3fa650e083f411a116a12dff2
5
5
  SHA512:
6
- metadata.gz: cd3efcb1e979ac3c63892e83a68fcd1b62db7d44297763e2fdc451251220c823efa2f27afc25d340902e5f56e0c8b7c53afd952df115eda9e78c95a143b8bb0f
7
- data.tar.gz: e8a972cb1ef2663d0247263984d06e82e24cfcf1e4e972788c3dc917a111c5ea88e8cd782191f7baf19d2804660ed93bd6c8241a58074010f112b22686ce6a55
6
+ metadata.gz: bcbbc65b5a3a3d66839d727e325238643973050b39248695e6623b4f45c7fd343ecea7cf52c8c59f70fe6caf63aace284c677d4cd50211ed4fef73e9fc984da7
7
+ data.tar.gz: 53147d0d353adf39e448f3ea82ac1c60dd1f7fee9168573d5802b052a3bd54fbd949fd9ac5b8d591ff134cc627c9204feeb07ffd1289304109b5eedd41ea08c0
data/AUDIT.md CHANGED
@@ -4,10 +4,29 @@
4
4
 
5
5
  The audit found real defects despite the original green test suite. The fixes
6
6
  below have regression coverage. The owner authorized publication of `0.1.0`
7
- on 2026-10-18. Publication still requires the selected tag's complete CI to
8
- pass and the protected publishing workflow to succeed. This audit establishes
7
+ on 2026-10-18. The exact tag's complete CI and protected publishing workflow
8
+ passed, and `0.1.0` is published on RubyGems and GitHub. This audit establishes
9
9
  the specific behaviors below, not the absence of all bugs.
10
10
 
11
+ ## Publication evidence
12
+
13
+ - Release tag `v0.1.0` points to commit
14
+ `e2203c0e0f573f1b8206d9abdac4ab8f838594b8`.
15
+ - [Publishing run 39115168826](https://github.com/yorzi/openui-rails/actions/runs/39115168826)
16
+ passed the complete reusable CI suite, package checks, protected environment
17
+ approval, RubyGems upload, and GitHub release draft creation.
18
+ - [RubyGems 0.1.0](https://rubygems.org/gems/openui-rails/versions/0.1.0) and
19
+ [GitHub Release v0.1.0](https://github.com/yorzi/openui-rails/releases/tag/v0.1.0)
20
+ expose the same artifact. SHA-256:
21
+ `275c124a9e8e9c82b471357e3f314e4c86d6255c8fc9ef0313be858525bffee5`.
22
+ The actual RubyGems download, GitHub asset, API digest, and `SHA256SUMS` match.
23
+ - The downloaded RubyGems artifact passed the fresh Rails host probe: install
24
+ generator, eager load, and HTTP rendering.
25
+ - [Documentation](https://openui-rails.wangyaodi.com/) uses GitHub Pages with
26
+ Actions. Cloudflare has a DNS-only CNAME to `yorzi.github.io`. GitHub verified
27
+ domain ownership through a TXT record and issued the certificate. HTTPS is
28
+ enforced. The release docs build checks stable and `/next/` channels.
29
+
11
30
  ## Confirmed defects corrected
12
31
 
13
32
  | Area | Defect | Correction and evidence |
@@ -71,8 +90,9 @@ complete accessibility, legal clearance, or an absence of future vulnerabilities
71
90
  `release`.
72
91
  - The repository is public. Security reports go to the address in `SECURITY.md`;
73
92
  public support uses GitHub Issues.
74
- - RubyGems has a pending Trusted Publisher for the exact workflow and
75
- environment. The first successful publication activates the gem's publisher.
93
+ - RubyGems Trusted Publishing for the exact workflow and environment was
94
+ successfully used for the first release. The public version page identifies
95
+ the GitHub Actions repository, workflow, and environment as its publisher.
76
96
  - The GitHub `release` environment requires approval by `yorzi`, allows the
77
97
  `main` branch only, and disallows administrator bypass. Self-review remains
78
98
  available for the single maintainer.
data/CHANGELOG.md CHANGED
@@ -6,6 +6,55 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.3.0] - 2026-10-19
10
+
11
+ ### Added
12
+
13
+ - A packaged, opt-in support-ticket reference host with SQLite persistence,
14
+ importmap, HTTP Turbo Streams, real Query/Mutation calls, host-owned
15
+ conversation continuation, and scoped snapshot recovery.
16
+ - `bin/check-reference` verifies the maintained host or a fresh host using only
17
+ the built artifact. Browser checks cover reload, lost envelopes, expired
18
+ identity, cross-tenant access, read-only roles, stale/duplicate actions, CSRF,
19
+ keyboard activation, and mobile layout. The reference host enables CSRF
20
+ itself, including during the documented test-environment review session.
21
+ - `bin/check-release --candidate` validates unpublished candidate metadata
22
+ without weakening the publication gate.
23
+ - `Surface` and `openui_surface` accept persisted `next_sequence` and
24
+ `completed` values to restore stream ordering after a page reload.
25
+
26
+ ### Fixed
27
+
28
+ - Conversation actions preserve the official runtime's user message, form name,
29
+ and form state as validated-by-host action arguments. Strict
30
+ `continue_conversation` schemas need to allow the metadata they consume.
31
+
32
+ ## [0.2.0] - 2026-10-18
33
+
34
+ ### Added
35
+
36
+ - `openui:library:prepare` installs prompt/spec exports of the exact pinned
37
+ default chat library and its upstream license without browser or Node tools.
38
+ Existing different files require explicit overwrite; outputs stay inside
39
+ the application root.
40
+ - `openui:doctor` reports local configuration, default library identity,
41
+ runtime checksums, and action-route failures without writes or network calls.
42
+ Browser setup and host policy checks remain explicitly unverified.
43
+ - Local `bin/check` and disposable `bin/check-browser` runners, with fixture
44
+ screenshots on both passing and failing tests and the same browser entry
45
+ point in CI.
46
+
47
+ ### Changed
48
+
49
+ - The install generator leads with the default chat library and setup checks.
50
+ Custom libraries retain the pinned CLI path and require a matching runtime.
51
+
52
+ ### Fixed
53
+
54
+ - Manifest name queries now read name-keyed collections used by the official
55
+ default-library spec, as well as the previously supported array format.
56
+ Fingerprint calculation is unchanged.
57
+
9
58
  ## [0.1.0] - 2026-10-18
10
59
 
11
60
  ### Fixed
@@ -67,5 +116,7 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
67
116
  - Gem-scoped RubyGems Trusted Publishing through GitHub OIDC, with a protected
68
117
  release environment and verified artifact handoff.
69
118
 
70
- [Unreleased]: https://github.com/yorzi/openui-rails/compare/v0.1.0...main
119
+ [Unreleased]: https://github.com/yorzi/openui-rails/compare/v0.3.0...main
120
+ [0.3.0]: https://github.com/yorzi/openui-rails/releases/tag/v0.3.0
121
+ [0.2.0]: https://github.com/yorzi/openui-rails/releases/tag/v0.2.0
71
122
  [0.1.0]: https://github.com/yorzi/openui-rails/releases/tag/v0.1.0
data/CONFIGURATION.md CHANGED
@@ -1,79 +1,11 @@
1
1
  # Configuration
2
2
 
3
- Configure the bridge in `config/initializers/openui.rb`. Rails owns identity,
4
- authorization, stream subscriptions, persistence, and snapshot recovery.
5
-
6
- | Setting | Default | Contract |
7
- | --- | --- | --- |
8
- | `transport` | `:turbo` | Factory preference: `:turbo`, `:action_cable`, or `:none`. Pass it explicitly to `Transports.build`; it does not create a subscription. |
9
- | `library_spec_path` | `nil` | JSON manifest from the exact runtime library. Enables server and browser fingerprint checks. |
10
- | `prompt_path` | `nil` | Prompt generated from that same library. |
11
- | `runtime_assets` | `:self_hosted` | Use `:external` only with explicit exact-version URLs. |
12
- | `local_runtime_path` | `"/openui"` | Public URL directory for self-hosted assets. |
13
- | `runtime_version` | pinned `0.2.1` | The fetch task accepts only the checksum-locked version. Other versions are unverified. |
14
- | `runtime_url` | derived self-hosted JS URL | Explicit override for a host-built or external runtime. |
15
- | `runtime_integrity` | pinned hash for the default runtime | Override for another JS asset. No default hash is assumed for custom URLs. |
16
- | `runtime_stylesheet_url` | derived self-hosted CSS URL | Required when using `:external` and `openui_stylesheet_tag`. |
17
- | `runtime_stylesheet_integrity` | pinned hash for the default runtime | Override for another CSS asset. |
18
- | `actions_endpoint` | `"/openui-rails/actions"` | Must match the host engine mount. |
19
- | `stream_byte_limit` | `1_048_576` | Positive integer; enforced by server writer and browser. |
20
- | `pending_byte_limit` | `32_768` | Positive byte-based flush threshold, at most the stream limit. Lower it for smaller, more frequent updates. There is no timer-based flush. |
21
- | `idempotency_ttl` | `900` seconds | Finite positive number. Replays are protected only within the store's lifetime and TTL. |
22
- | `idempotency_store` | process-local `MemoryStore` | Use a shared atomic store for multiple processes. See the contract below. |
23
- | `idempotency_scope` | derived actor/tenant identity | Optional callable receiving `Invocation`; return a stable, JSON-serializable namespace for custom identity types. |
24
- | `actor_resolver` | host `current_user`, if available | Callable receiving the engine controller. Host authentication filters are inherited. |
25
- | `surface_resolver` | `nil` | Callable `(surface_id, actor:, context:)`; return the scoped surface, or `nil` to deny. Without it, the authorizer owns resource/version checks. |
26
- | `authorize_action` | `nil` | Global authorizer receiving `Invocation`. Missing authorization denies the action. Per-action `authorize:` takes precedence. |
27
- | `on_error` | `nil` | Server stream-error hook `(error, message_id:)`. Do not log credentials or unredacted provider requests. |
28
- | `action_registry` | lazy `Actions::Registry` | Allowlisted action definitions. |
29
-
30
- `library_name` and `surface_id_param` are legacy metadata settings. They do not
31
- select a runtime library or change the endpoint's `surface_id` wire key.
32
-
33
- After you create the library files, call
34
- `OpenUI::Rails.configuration.validate!` to check required configuration and
35
- read the actual manifest and configured prompt files.
36
- Boot does not call it automatically, so setup tasks can run before files exist.
37
-
38
- ## Shared idempotency store
39
-
40
- The dispatcher supplies a SHA-256 key scoped to server actor and tenant identity.
41
- It supplies a digest of the entire validated request separately.
42
-
43
- ```ruby
44
- claim(key, ttl:, digest:)
45
- # => [:claimed, nil, digest, claim_token] # this request owns execution
46
- # => [:pending, nil, stored_digest, token] # execution is in progress
47
- # => [:replay, result, stored_digest, token] # completed, including nil/false
48
-
49
- record(key, result, claim_token: token)
50
- ```
51
-
52
- Implement `claim` atomically. Make `claim_token` unique for every new claim.
53
- Ignore a `record` call whose token no longer owns the key. Preserve completed
54
- `nil` and `false` results instead of treating them as pending.
55
-
56
- The default identity is `[class, id]` for records and `[class, value]` for scalar
57
- identities. Unsupported identity objects need `idempotency_scope`. Scope must
58
- come from trusted server state, not a client-supplied user or tenant ID.
59
-
60
- A failed handler leaves a pending claim until expiry because its side effects
61
- may already have happened. A handler that outlives the TTL can overlap a later
62
- claim. Choose a suitable TTL and enforce business-level uniqueness or
63
- transactions for irreversible operations. Process-local memory does not survive
64
- restarts and cannot coordinate separate workers.
65
-
66
- ## Browser errors and recovery
67
-
68
- Listen for `openui:error` to show a host-owned error or fallback. Listen for
69
- `openui:snapshot-required` to fetch an authorized, authoritative snapshot.
70
- The bridge emits these events; it does not implement the host's fallback UI,
71
- snapshot endpoint, reconnection policy, or persistence.
72
-
73
- The action bridge rejects authentication redirects and non-JSON, malformed, or
74
- mismatched results. An expired-session redirect emits `unauthorized`; a broken
75
- response contract emits `invalid_response`. Host callbacks may still redirect
76
- HTTP requests, but a redirect is never a successful JSON action result.
77
-
78
- Configure a matching manifest in production. Without one, the bridge cannot
79
- verify that the model prompt, stored output, and runtime library agree.
3
+ Use the [configuration guide](https://openui-rails.wangyaodi.com/configuration/)
4
+ for settings, defaults, and the shared idempotency-store contract.
5
+ Review [production setup](https://openui-rails.wangyaodi.com/production/)
6
+ before deploying.
7
+
8
+ The site documents the latest release. For `main`, use
9
+ [/next/configuration/](https://openui-rails.wangyaodi.com/next/configuration/).
10
+ To read offline, open the [guide source](docs/_getting_started/configuration.md)
11
+ at the tag matching your installed gem.
data/CONTRIBUTING.md CHANGED
@@ -14,12 +14,18 @@ bundle exec bin/rails db:test:prepare
14
14
 
15
15
  ## Before you open a pull request
16
16
 
17
+ Use `bin/check` for the local lint, unit/integration, RubyLLM, and built-gem
18
+ checks. Add `--browser` for deterministic browser tests and `--docs` for the
19
+ versioned site build. For the real runtime, fetch its pinned assets explicitly
20
+ and pass `--runtime tmp/real-runtime`. See [agent verification](DEVELOPMENT.md)
21
+ for focused runs, screenshots, and test boundaries.
22
+
17
23
  ```bash
18
24
  bundle exec bin/rails test # unit + integration tests
19
25
  bundle exec bin/rails test:system # browser (system) tests, needs Chrome
20
26
  bundle exec rubocop # style (rubocop-rails-omakase)
21
27
  bundle exec gem build openui-rails.gemspec
22
- bundle exec ruby bin/smoke-package openui-rails-0.1.0.gem
28
+ bundle exec ruby bin/smoke-package openui-rails-0.3.0.gem
23
29
  bundle exec bundler-audit check --update
24
30
  bundle exec ruby -Itest test/compatibility/ruby_llm_smoke.rb
25
31
  ```
@@ -57,6 +63,28 @@ cases.
57
63
  prompt CLI; pin exact versions.
58
64
  - Write commit messages that explain the *why*.
59
65
 
66
+ ## Documentation
67
+
68
+ Keep the README as a short introduction and navigation page. Write setup,
69
+ configuration, feature guides, and API contracts in `docs/`; the root
70
+ `CONFIGURATION.md` and `UPGRADING.md` link there. Keep contributor instructions,
71
+ security policy, release procedures, and audit evidence in the repository.
72
+
73
+ Use [ROADMAP.md](ROADMAP.md) for proposed work toward 1.0. Record delivered
74
+ changes in [CHANGELOG.md](CHANGELOG.md). A planned API is not a supported API.
75
+ Update the relevant guide with each public API change and add migration steps
76
+ when existing applications need changes.
77
+
78
+ Build documentation before submitting it:
79
+
80
+ ```sh
81
+ docs/bin/build.sh
82
+ ```
83
+
84
+ The build includes the release docs at `/` and your working tree at `/next/`.
85
+ Preview with `docs/bin/serve.sh`; it binds to `127.0.0.1:4000`. Stop it when you
86
+ finish reviewing.
87
+
60
88
  ## Reporting security issues
61
89
 
62
90
  Please do not open a public issue for a security problem. See `SECURITY.md`.
data/DEVELOPMENT.md ADDED
@@ -0,0 +1,89 @@
1
+ # Development and verification
2
+
3
+ Use `test/dummy` as the maintained local host. Temporary generated hosts verify
4
+ the built gem. Keep examples synthetic and provider-free unless a task explicitly
5
+ authorizes a live call. Follow this loop for each feature:
6
+
7
+ 1. Reproduce the behavior with a focused test through its public entry point.
8
+ 2. Implement the change and update its guide in the same commit.
9
+ 3. Run the focused checks, then `bin/check`. Run database suites sequentially.
10
+ 4. For browser behavior, run the relevant suite, inspect its screenshots, and
11
+ use browser tools for keyboard, layout, or mobile questions left unresolved.
12
+ 5. Commit a completed unit with its actual verification results. Stop any
13
+ task-owned service before finishing.
14
+
15
+ ## Reference workflow
16
+
17
+ ```sh
18
+ bin/check-reference
19
+ bin/check-reference --runtime tmp/real-runtime
20
+ bin/check-reference --gem tmp/package/openui-rails-0.3.0.gem --runtime tmp/real-runtime
21
+ # Focus one browser scenario:
22
+ bin/check-reference --runtime tmp/real-runtime --name test_a_lost_turbo_envelope_recovers_from_the_scoped_snapshot
23
+ ```
24
+
25
+ The first command verifies reference-host transactions in a temporary SQLite
26
+ database. The browser option uses the real renderer and screenshot evidence.
27
+ The gem option generates an isolated consumer using the example packaged in
28
+ that artifact; it imports no dummy-app fixtures. `bin/check --runtime` includes
29
+ this consumer flow. CI runs the host transaction tests in its Ruby/Rails matrix
30
+ and the artifact browser flow in the system job.
31
+
32
+ Add `--host tmp/support-desk` with `--gem` to retain a synthetic review host.
33
+ It refuses existing directories and starts no persistent service. Follow the
34
+ site's Reference Workflow guide for its explicit loopback review command.
35
+
36
+ ## Checks
37
+
38
+ ```sh
39
+ bin/check
40
+ bin/check --browser --docs
41
+ # Requires npm and network only for this explicit fetch:
42
+ bundle exec rake "app:openui:runtime:fetch[$PWD/tmp/real-runtime]"
43
+ bin/check-browser --runtime tmp/real-runtime
44
+ # Run all local checks including both browser layers:
45
+ bin/check --runtime tmp/real-runtime --docs
46
+ # Focus on one browser test file:
47
+ bin/check-browser test/system/openui_confirmation_system_test.rb
48
+ ```
49
+
50
+ Chrome is required. Set `CHROME_BIN` for a nonstandard executable. Selenium
51
+ manages the driver; its first run may need a download. Each browser run uses a
52
+ temporary SQLite database and stores passed and failed fixture screenshots in
53
+ the printed `tmp/browser/` directory. Screenshots are evidence for visual
54
+ review, not a substitute for assertions. Logs, databases, and screenshots stay
55
+ in ignored directories. Do not put production data in them.
56
+
57
+ The Capybara server and driver port probe bind loopback. Test processes close
58
+ their browser sessions and remove the temporary database on exit. This is not
59
+ a browser network sandbox. The stub suite exercises bridge failure cases; the
60
+ real-runtime suite verifies the pinned renderer, library identity, actions,
61
+ tools, and keyboard behavior. Neither proves live-provider compatibility.
62
+
63
+ ## Refresh the default library exports
64
+
65
+ When changing the pinned runtime, regenerate from its checksum-verified bundle:
66
+
67
+ ```sh
68
+ bin/export-default-library tmp/real-runtime
69
+ bin/export-default-library tmp/real-runtime --check
70
+ ```
71
+
72
+ This maintainer command uses the existing Selenium/Chrome development tools,
73
+ closes the browser afterward, and preserves the upstream license and provenance.
74
+ Review the generated files and run the real-runtime tests. Applications use the
75
+ exported files inside the gem and need none of these browser tools for preparation.
76
+
77
+ ## Installed artifact and release checks
78
+
79
+ `bin/check` builds into `tmp/package/` and tests a new Rails host using that
80
+ artifact. It verifies default library preparation, repeat runs, overwrite
81
+ rejection, missing-setup doctor exits, eager load, and HTTP mount rendering.
82
+ With `--runtime`, it also verifies a successful doctor report, actual rendering,
83
+ an explicitly authorized CSRF-protected action, and a 390px mobile page in a
84
+ fresh host. The host reads its prompt/spec from the gem, never test fixtures.
85
+ Fixture screenshots use the same `tmp/browser/` tree. CI runs this path too.
86
+ This does not establish external adoption or remote CI success.
87
+ Dependency-advisory refreshes remain explicit network operations; run
88
+ `bundle exec bundler-audit check --update` before a release. Follow
89
+ [Releasing](RELEASING.md) for the remaining publication checks.