solana-studio 0.5.1 → 0.5.2
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/README.md +38 -0
- data/app/views/solana_studio/auth/_wallet_credential.html.erb +71 -0
- data/lib/solana_studio/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fa775c67a1f3ae154dabf231c294c86e6a03dc74f2866fcfdab2cb7f8bf9da9b
|
|
4
|
+
data.tar.gz: 6dd4bd255c9ea0d99c8daaeff4a176152226e63a61f36943869f70f3e9a57441
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b52fd18bf1bab93c0a060d5cc135b1e9bc81bdfb5b32b9771251f831ffaaa5653891706927904e5e57a852094c3a4e41a45350e84bcca16f4f30cd9913bdbc55
|
|
7
|
+
data.tar.gz: 701023cfadfee72780409a021e2e2bfa2223cb3366a07659409764f5aa7f4aa1fb2adc961a5b7ba68103fe5263dfa77506f659727c6c315171d63faa4d16f735
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
The format is [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). This project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
4
4
|
|
|
5
|
+
## Unreleased
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- **The wallet sign-in button, contributed into studio-engine's auth modal** (`app/views/solana_studio/auth/_wallet_credential.html.erb`). Part of the base/bolt-on split: studio-engine plus McRitchie Studio is the template every app is built from, web2 and web3 alike, and this gem plus Turf Monster is the web3 bolt-on. Sign-in is a base concern so the modal stays in the engine; **wallets are not**, so the button moved here. The engine renders whatever resolves at `solana_studio/auth/wallet_credential` and nothing when the path is empty, so bundling this gem IS the registration and a web2 app carries no wallet markup at all. Deliberately NOT solved by giving this gem its own auth modal: that would fork a surface both apps sign in through, which is how the wallet picker reached three drifting copies before it was promoted. The engine keeps both halves of the existing gate (`Studio.auth_method?(:wallet)` and `Studio.feature?(:web3)`) so the hub — which bundles this gem for its signing primitives with web3 off — still renders a web2 sign-in modal.
|
|
9
|
+
|
|
10
|
+
### Tests
|
|
11
|
+
- `test/auth_credential_test.rb` (7): the partial sits at the path the engine resolves, the click handler consults the modal's age gate, visibility binds to the shared `methodOn('wallet')` toggle, `modal_store` is required with no default, the swap carries the picker's `backTo`/`ageAttested` contract, the brand gradient id is namespaced against collisions, and the mark stays inline rather than becoming a sprockets asset request. Every assertion reads ERB-comment-stripped source, because this file documents its own contract in prose and a bare grep would match the paragraph instead of the code — proven by mutating the gate into a comment and watching it go red.
|
|
12
|
+
- `test/gemspec_test.rb` and `.github/workflows/gem-ci.yml` name the new partial alongside the modal, so a `spec.files` glob that stopped matching it fails at build rather than in a consumer.
|
|
13
|
+
|
|
5
14
|
## Unreleased — targets v0.5.0 (minor)
|
|
6
15
|
|
|
7
16
|
Ships the gem's first Rails half, and its first CI. The version number is
|
data/README.md
CHANGED
|
@@ -177,6 +177,44 @@ attributes, so a host can adopt it before changing its layout.
|
|
|
177
177
|
Requires studio-engine's modal host (`Alpine.store('modals')`) and its shared
|
|
178
178
|
modal blocks. The JS is `solana_studio/network_guard.js` on the asset path.
|
|
179
179
|
|
|
180
|
+
### Wallet sign-in button (the credential slot)
|
|
181
|
+
|
|
182
|
+
studio-engine owns the sign-in modal, because every app in the ecosystem signs
|
|
183
|
+
people in and most of them are web2. This gem owns the **wallet button** inside
|
|
184
|
+
it, because only a web3 app has wallets.
|
|
185
|
+
|
|
186
|
+
There is **nothing to wire up.** The engine's auth modal looks for a partial at
|
|
187
|
+
one fixed path and renders whatever it finds:
|
|
188
|
+
|
|
189
|
+
solana_studio/auth/_wallet_credential
|
|
190
|
+
|
|
191
|
+
Bundling this gem puts that partial on the host's view path, so the button
|
|
192
|
+
appears. An app that does not bundle it finds nothing and renders nothing — no
|
|
193
|
+
wallet markup ships to a newsletter app, and no `render` call has to be deleted
|
|
194
|
+
to keep it out.
|
|
195
|
+
|
|
196
|
+
The engine asks two questions and needs both answered yes:
|
|
197
|
+
|
|
198
|
+
| Question | Answered by | Where |
|
|
199
|
+
|---|---|---|
|
|
200
|
+
| Does this app *want* wallet sign-in? | `Studio.auth_method?(:wallet)` and `Studio.feature?(:web3)` | the host's `config/initializers/studio.rb` |
|
|
201
|
+
| Is there a layer that *implements* it? | this partial resolving on the view path | bundling this gem |
|
|
202
|
+
|
|
203
|
+
Both matter. McRitchie Studio bundles this gem for the Ruby signing primitives
|
|
204
|
+
while shipping web3 **off**, so the partial is present and the button is
|
|
205
|
+
correctly absent. And an app that declares `:wallet` but forgets the gem gets no
|
|
206
|
+
button rather than a missing-partial error in front of someone signing in.
|
|
207
|
+
|
|
208
|
+
The partial renders inside the modal's own Alpine scope and borrows three
|
|
209
|
+
members from it — `methodOn('wallet')` for visibility, `attested()` for the
|
|
210
|
+
legal-age gate, and `props.submitting` for the disabled state. It takes one
|
|
211
|
+
required local, `modal_store`, which the engine passes.
|
|
212
|
+
|
|
213
|
+
Why a contributed button and not a second auth modal: Turf Monster wants Google
|
|
214
|
+
plus magic-link plus wallet, McRitchie Studio wants Google plus magic-link. A
|
|
215
|
+
forked modal would put a surface both apps sign in through into two files, which
|
|
216
|
+
is how the wallet picker reached three copies before it was promoted.
|
|
217
|
+
|
|
180
218
|
## Dependencies
|
|
181
219
|
|
|
182
220
|
- `ed25519` (~> 1.3) — Ed25519 signing
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
<%#
|
|
2
|
+
The Solana credential button for studio-engine's SIGN-IN modal.
|
|
3
|
+
|
|
4
|
+
This is the gem half of the engine's CREDENTIAL SLOT seam. The auth modal is a
|
|
5
|
+
BASE modal: every app in the ecosystem signs people in, and most of them are
|
|
6
|
+
web2, so the modal itself stays in studio-engine and is never forked. What
|
|
7
|
+
varies is which credentials it offers. Google and magic-link are implemented by
|
|
8
|
+
the base template and render from the engine directly. Wallet is implemented
|
|
9
|
+
HERE, by the web3 bolt-on, and reaches the modal by being on the view path.
|
|
10
|
+
|
|
11
|
+
The engine renders this at a fixed path and only when it resolves:
|
|
12
|
+
|
|
13
|
+
solana_studio/auth/_wallet_credential
|
|
14
|
+
|
|
15
|
+
So an app that does not bundle this gem finds nothing, renders nothing, and
|
|
16
|
+
carries no wallet markup at all. An app that does bundle it gets the button
|
|
17
|
+
with no configuration and no registration call. Presence IS the wiring.
|
|
18
|
+
|
|
19
|
+
WHY A PARTIAL AND NOT A COPY OF THE MODAL. Turf Monster wants Google plus
|
|
20
|
+
magic-link plus wallet; McRitchie Studio wants Google plus magic-link. Solving
|
|
21
|
+
that by giving the gem its own auth modal would fork a surface both apps sign
|
|
22
|
+
in through, and the two copies would drift the way the wallet picker drifted
|
|
23
|
+
into three copies before it was promoted. One modal, one contributed button.
|
|
24
|
+
|
|
25
|
+
SCOPE — this renders INSIDE the engine auth modal's root x-data, so these
|
|
26
|
+
members are in scope and are the seam's contract:
|
|
27
|
+
|
|
28
|
+
methodOn(m) whether credential m should show. Reads props.methods per key
|
|
29
|
+
and falls back to the app's own Studio.auth_method? default,
|
|
30
|
+
which for wallet is auth_method?(:wallet) AND feature?(:web3).
|
|
31
|
+
attested() the legal-age gate. Returns false and paints the error when
|
|
32
|
+
the app requires attestation and the box is unticked. Every
|
|
33
|
+
credential CTA in the modal calls it first; skipping it here
|
|
34
|
+
would make wallet the one way around the gate.
|
|
35
|
+
|
|
36
|
+
THE HANDLER IS INLINE, not a method on a nested x-data, and that is deliberate.
|
|
37
|
+
A child x-data would reach attested() through Alpine's prototypal scope merge,
|
|
38
|
+
which works but is subtle enough that a later reader could "simplify" the
|
|
39
|
+
nesting away and silently drop the age gate. An expression in the attribute
|
|
40
|
+
reads the enclosing scope directly, with nothing to get wrong.
|
|
41
|
+
|
|
42
|
+
Locals:
|
|
43
|
+
modal_store Alpine store name backing the modal. The engine's real host
|
|
44
|
+
uses "modals"; the living style guide mounts a page-scoped host
|
|
45
|
+
and passes "dsModals". Required, no default, because a wrong
|
|
46
|
+
store name fails as a dead button rather than as an error.
|
|
47
|
+
%>
|
|
48
|
+
<% modal_store = local_assigns.fetch(:modal_store) %>
|
|
49
|
+
<%# The picker this opens is the wallet-connect modal. backTo returns the user
|
|
50
|
+
here if they back out of the brand list, and ageAttested carries the gate
|
|
51
|
+
they already passed so the picker does not ask a second time. %>
|
|
52
|
+
<button type="button"
|
|
53
|
+
@click="attested() && $store.<%= modal_store %>.swap('wallet-connect', { backTo: 'auth', ageAttested: true })"
|
|
54
|
+
x-show="methodOn('wallet')"
|
|
55
|
+
:disabled="!!props.submitting"
|
|
56
|
+
class="btn btn-neutral btn-lg w-full gap-3 mb-3 disabled:cursor-wait">
|
|
57
|
+
<%# The Solana wordmark, inline rather than an asset request: this gem ships no
|
|
58
|
+
image and a host that had to precompile one would get a silent 404 on a
|
|
59
|
+
sprockets app. The gradient id is namespaced so two Solana marks on one
|
|
60
|
+
page cannot collide. %>
|
|
61
|
+
<svg width="18" height="14" viewBox="0 0 397 311" fill="none" x-show="props.submitting !== 'wallet'" aria-hidden="true">
|
|
62
|
+
<defs><linearGradient id="solana-studio-auth-grad" x1="361" y1="-9" x2="153" y2="389" gradientUnits="userSpaceOnUse">
|
|
63
|
+
<stop offset="0" stop-color="#00FFA3"/><stop offset="1" stop-color="#DC1FFF"/>
|
|
64
|
+
</linearGradient></defs>
|
|
65
|
+
<path d="M65 234c2-2 6-4 9-4h317c6 0 9 7 5 11l-63 63c-2 2-6 4-9 4H6c-6 0-9-7-5-11l64-63z" fill="url(#solana-studio-auth-grad)"/>
|
|
66
|
+
<path d="M65 4c2-2 6-4 9-4h317c6 0 9 7 5 11l-63 63c-2 2-6 4-9 4H6c-6 0-9-7-5-11L65 4z" fill="url(#solana-studio-auth-grad)"/>
|
|
67
|
+
<path d="M333 119c-2-2-6-4-9-4H7c-6 0-9 7-5 11l63 63c2 2 6 4 9 4h317c6 0 9-7 5-11l-63-63z" fill="url(#solana-studio-auth-grad)"/>
|
|
68
|
+
</svg>
|
|
69
|
+
<span x-show="props.submitting === 'wallet'" class="spinner" aria-hidden="true"></span>
|
|
70
|
+
<span x-text="props.submitting === 'wallet' ? 'Connecting…' : 'Solana'"></span>
|
|
71
|
+
</button>
|
|
@@ -16,5 +16,5 @@ module SolanaStudio
|
|
|
16
16
|
# through the normal cycle. Splitting the version out is the same shape
|
|
17
17
|
# studio-engine already uses (lib/studio/version.rb) and hands each file back
|
|
18
18
|
# to its real owner: this one to the release, the gemspec to the PR.
|
|
19
|
-
VERSION = "0.5.
|
|
19
|
+
VERSION = "0.5.2"
|
|
20
20
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: solana-studio
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.5.
|
|
4
|
+
version: 0.5.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Alex McRitchie
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-09-01 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: ed25519
|
|
@@ -38,6 +38,7 @@ files:
|
|
|
38
38
|
- LICENSE
|
|
39
39
|
- README.md
|
|
40
40
|
- app/assets/javascripts/solana_studio/network_guard.js
|
|
41
|
+
- app/views/solana_studio/auth/_wallet_credential.html.erb
|
|
41
42
|
- app/views/solana_studio/modals/_network_mismatch.html.erb
|
|
42
43
|
- lib/solana-studio.rb
|
|
43
44
|
- lib/solana/auth_verifier.rb
|