studio-engine 0.67.0 → 0.67.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3ffd4e2260ecf5e4ed81cbe17b45001ac14b3bcbf576b4fd79b506bfa2fff6dc
4
- data.tar.gz: d7f03282009eeb8f914637df864769fb5846808d4ccc270a1285c04564b18418
3
+ metadata.gz: 69e6eab8f9186157077a967e6fd21a6b075a94245969f26a42b57bf5154e59f0
4
+ data.tar.gz: d88f16a0143527684b091c40c0fd33dfc561661381fdcdc32ac08d09fa27119b
5
5
  SHA512:
6
- metadata.gz: 1ab14b588d1d5382cc1738205472ba01b3f7aeb4442b026a506a824e777060eeae59ab7873d3176bfb6fd5f1ca95633a052e02b69ebe8f7715a6c9a8cdc1d821
7
- data.tar.gz: 9256f176a552cea09a38ec5e56b32749ce4e419f5231b90971e6c14f2099983e6b4be646cdac8cc5efdef2e6d476714875c00ff1beae980f66c31752446c7123
6
+ metadata.gz: de70d91aedcb0d23734ddde03e24272df70a982eea531583247608451f5da7bf86f485857cdc6ceeefaedf91319d318e56254d6e90c702be91b4317f0d34af68
7
+ data.tar.gz: 507a127ab69e870f0f82c0cfff93b5ca2d68b5241c4925eb58fae838ff78821a219614c31c2952fd7fe197b2f2c7eb2e906bfd3feff5ff3d9e973e8cdce15e78
@@ -76,9 +76,35 @@
76
76
  # Auth method-toggle defaults — mirror the app's Studio.auth_method? config;
77
77
  # Solana Wallet also needs the web3 capability, so it defaults OFF on an app
78
78
  # (like McRitchie Studio) that ships web3 off.
79
+ #
80
+ # web3_gem is the THIRD term, and it answers a question neither of the other
81
+ # two asks. auth_methods declares which CREDENTIALS an app accepts; features
82
+ # gates PRODUCT SURFACES — lib/studio.rb spells that split out where it
83
+ # deliberately does NOT gate the /auth/solana routes on :web3. Both are
84
+ # POLICY. Whether the wallet picker can RENDER AT ALL is template resolution,
85
+ # and the Solana button does nothing except swap to that picker. A trigger
86
+ # must carry at least the gate its target's REGISTRATION carries (see
87
+ # web3_gem above, which wraps the wallet-connect registration) or it opens an
88
+ # empty panel — the same failure the three specimen cards had, through a
89
+ # different door.
79
90
  ml_default = Studio.auth_method?(:magic_link)
80
91
  g_default = Studio.auth_method?(:google)
81
- w_default = Studio.auth_method?(:wallet) && web3_on
92
+ w_default = Studio.auth_method?(:wallet) && web3_on && web3_gem
93
+
94
+ # The Sign in card's toggles. Solana Wallet is DROPPED where the gem is
95
+ # absent, because that checkbox is the door this page actually opens:
96
+ # methodOn('wallet') reads props.methods.wallet — the toggle's own boolean —
97
+ # BEFORE it ever falls back to the defaults above, so a ticked box overrides
98
+ # w_default outright. Leaving it offered would keep the empty panel one click
99
+ # away in EVERY base-app configuration, including the stock auth_methods
100
+ # default that declares no :wallet at all. A control that cannot do its one
101
+ # job is worse than an absent one; the section prose says why it is gone.
102
+ auth_toggles = [
103
+ { model: "opts.magicLink", label: "Magic Link" },
104
+ { model: "opts.google", label: "Google" }
105
+ ]
106
+ auth_toggles << { model: "opts.wallet", label: "Solana Wallet" } if web3_gem
107
+ auth_toggles << { model: "opts.terms", label: "Terms" }
82
108
 
83
109
  # Active-card glow-match expression builder: yields an Alpine boolean that is
84
110
  # true when $store.dsModals.current() is THIS specimen's modal. It discriminates
@@ -365,8 +391,12 @@
365
391
  :class="$store.dsModals.cardClasses()">
366
392
 
367
393
  <%# --- Auth suite --- %>
394
+ <%# web3_gem is passed, not recomputed: this file owns the lookup (see
395
+ above) and the auth modal's Solana button needs the SAME answer,
396
+ because that button's only job is to swap to the wallet-connect
397
+ registration gated on it a few lines down. One lookup, two readers. %>
368
398
  <template x-if="$store.dsModals.current().id === 'auth'">
369
- <div><%= render "style/modals/auth" %></div>
399
+ <div><%= render "style/modals/auth", web3_gem: web3_gem %></div>
370
400
  </template>
371
401
 
372
402
  <%# --- Onboarding step (its card now lives in Profile) --- %>
@@ -629,6 +659,11 @@
629
659
  magic-link-sent &rarr; magic-link-resent</code>. Toggle the methods below a
630
660
  card, then open it to watch them gate the modal. The live card
631
661
  <strong>glows</strong>, and the glow follows the step machine as you advance.
662
+ <% unless web3_gem %>
663
+ <strong>Solana sign-in needs solana-studio, which this app does not
664
+ bundle</strong>, so that button and its toggle are absent here &mdash;
665
+ nothing registers the wallet picker the button opens.
666
+ <% end %>
632
667
  </p>
633
668
  </div>
634
669
  <div class="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
@@ -639,12 +674,7 @@
639
674
  card_data: "opts: { magicLink: #{ml_default}, google: #{g_default}, wallet: #{w_default}, terms: true }",
640
675
  open_expr: "$store.dsModals.open('auth', { step: 'credentials', picksRequired: 6, methods: { magicLink: opts.magicLink, google: opts.google, wallet: opts.wallet }, terms: opts.terms })",
641
676
  glow_when: ds_glow.call("auth", step: "credentials"),
642
- toggles: [
643
- { model: "opts.magicLink", label: "Magic Link" },
644
- { model: "opts.google", label: "Google" },
645
- { model: "opts.wallet", label: "Solana Wallet" },
646
- { model: "opts.terms", label: "Terms" }
647
- ] } do %>
677
+ toggles: auth_toggles } do %>
648
678
  <div class="pointer-events-none w-40 rounded-lg bg-surface border border-subtle shadow p-4 space-y-2 text-center">
649
679
  <span class="block h-2 w-16 mx-auto rounded" style="background: var(--color-text); opacity: .18"></span>
650
680
  <span class="block h-6 w-full rounded border" style="border-color: var(--color-border-strong)"></span>
@@ -17,10 +17,27 @@
17
17
  resets; Solana swaps to the wallet-connect picker (a real ported specimen).
18
18
  No real auth happens — the demo shows the real UI.
19
19
 
20
+ LOCALS:
21
+ web3_gem (Boolean, required) — does solana-studio resolve. style/_modals
22
+ owns the lookup and registers wallet-connect behind the same flag; the
23
+ Solana button below is rendered only when it is true, because a button that
24
+ swaps to an unregistered id opens an empty panel. Fetched without a default
25
+ on purpose: a caller that forgets it should fail loudly here rather than
26
+ silently drop Solana sign-in from an app that has the gem.
27
+
28
+ NOT gated on web3_gem, deliberately: _methodDefaults.wallet below. It is the
29
+ fallback methodOn uses when an opener passes no methods hash, and on a base
30
+ app nothing reaches it — the Sign in card always passes explicit booleans, and
31
+ the only opener that omits them is the wallet picker's back button, which
32
+ needs the gem to exist at all. Adding the term there would read like a third
33
+ gate while changing no rendered outcome and no behaviour, and a gate that
34
+ cannot be shown to bite is decoration. The trigger below is the real gate.
35
+
20
36
  CRITICAL: rendered inside <template x-if="id==='auth'"> — Alpine requires a
21
37
  SINGLE root, so everything lives inside the outer <div>. The x-data is a
22
38
  double-quoted attribute: keep it free of double-quotes and backticks.
23
39
  %>
40
+ <% web3_gem = local_assigns.fetch(:web3_gem) %>
24
41
  <div x-data="{
25
42
  email: '',
26
43
  ageAttested: false,
@@ -167,21 +184,36 @@
167
184
  <p role="alert" class="text-red-400 text-xs -mt-2 mb-3" x-text="props.googleError"></p>
168
185
  </template>
169
186
 
170
- <%# 2. Solana — progresses to the Connect Wallet picker modal. Gated on
171
- methodOn('wallet') (default OFF where web3 is off, e.g. McRitchie Studio). %>
172
- <button @click="openWalletHub()" x-show="methodOn('wallet')" :disabled="!!props.submitting"
173
- class="btn btn-neutral btn-lg w-full gap-3 mb-3 disabled:cursor-wait">
174
- <svg width="18" height="14" viewBox="0 0 397 311" fill="none" x-show="props.submitting !== 'wallet'" aria-hidden="true">
175
- <defs><linearGradient id="auth-solana-grad" x1="361" y1="-9" x2="153" y2="389" gradientUnits="userSpaceOnUse">
176
- <stop offset="0" stop-color="#00FFA3"/><stop offset="1" stop-color="#DC1FFF"/>
177
- </linearGradient></defs>
178
- <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(#auth-solana-grad)"/>
179
- <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(#auth-solana-grad)"/>
180
- <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(#auth-solana-grad)"/>
181
- </svg>
182
- <span x-show="props.submitting === 'wallet'" class="spinner" aria-hidden="true"></span>
183
- <span x-text="props.submitting === 'wallet' ? 'Connecting…' : 'Solana'"></span>
184
- </button>
187
+ <%# 2. Solana — progresses to the Connect Wallet picker modal. TWO gates,
188
+ asking two different questions, and only one of them is Alpine's:
189
+
190
+ x-show methodOn('wallet') POLICY does this app offer wallet as a
191
+ credential, and has the specimen card's toggle turned it on. Reads
192
+ props.methods.wallet first, so the card's checkbox overrides the
193
+ server default outright.
194
+ Ruby web3_gem CAPABILITY — does solana-studio resolve, so
195
+ that something actually REGISTERED the wallet-connect id this button
196
+ swaps to. style/_modals wraps that registration in the same gate.
197
+
198
+ The policy gate cannot stand in for the capability one: a base app can
199
+ answer yes to the first and no to the second, and then the button opens
200
+ an empty panel. It has to be the RUBY gate because the toggle can flip
201
+ every Alpine term, and a control the operator can tick is not a gate. %>
202
+ <% if web3_gem %>
203
+ <button @click="openWalletHub()" x-show="methodOn('wallet')" :disabled="!!props.submitting"
204
+ class="btn btn-neutral btn-lg w-full gap-3 mb-3 disabled:cursor-wait">
205
+ <svg width="18" height="14" viewBox="0 0 397 311" fill="none" x-show="props.submitting !== 'wallet'" aria-hidden="true">
206
+ <defs><linearGradient id="auth-solana-grad" x1="361" y1="-9" x2="153" y2="389" gradientUnits="userSpaceOnUse">
207
+ <stop offset="0" stop-color="#00FFA3"/><stop offset="1" stop-color="#DC1FFF"/>
208
+ </linearGradient></defs>
209
+ <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(#auth-solana-grad)"/>
210
+ <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(#auth-solana-grad)"/>
211
+ <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(#auth-solana-grad)"/>
212
+ </svg>
213
+ <span x-show="props.submitting === 'wallet'" class="spinner" aria-hidden="true"></span>
214
+ <span x-text="props.submitting === 'wallet' ? 'Connecting…' : 'Solana'"></span>
215
+ </button>
216
+ <% end %>
185
217
 
186
218
  <%# "or" divider — only when magic-link AND a social method are both on. %>
187
219
  <div class="relative my-4" x-show="methodOn('magicLink') && (methodOn('google') || methodOn('wallet'))">
@@ -1,3 +1,3 @@
1
1
  module Studio
2
- VERSION = "0.67.0"
2
+ VERSION = "0.67.1"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: studio-engine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.67.0
4
+ version: 0.67.1
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-09-01 00:00:00.000000000 Z
11
+ date: 2026-09-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails