Release cookie-free Persimmons vault link 0.6.0

This commit is contained in:
matcha committed 2026-10-04 08:05:18 +00:00
1 parent 53c4bb50f4
commit 1aa3cffaf2
32 files changed
+1535 -624

No files matched your search

+17 -60
View File
@@ -26,86 +26,43 @@ button,.buttonLink{appearance:none;border:1px solid var(--line);border-radius:11
.field{display:grid;gap:6px;margin-bottom:12px}.field label{font-size:12px;font-weight:720;color:var(--muted)}.fieldHelp{margin-top:-2px;color:var(--muted);font-size:11px}.checks{display:flex;gap:8px;flex-wrap:wrap}.check{display:flex;gap:6px;align-items:center;border:1px solid var(--line);border-radius:999px;padding:7px 9px;font-size:12px}.check input{width:auto}.advanced{margin-top:14px;border-top:1px solid var(--line);padding-top:13px}.advanced summary{cursor:pointer;font-size:13px;font-weight:720}.advanced .inside{margin-top:12px}.composerNav{display:flex;justify-content:space-between;gap:10px;margin-top:18px}
.footerNote{font-weight:400;font-style:normal;padding:18px 12px 0;color:var(--muted);font-size:11.5px;line-height:1.5;text-align:center}.footerNote strong{display:block;color:var(--ink);margin-bottom:3px}.apiP{font-style:italic;font-weight:inherit}
@media(max-width:720px){body{padding:16px}.hero{padding-top:22px}.shellTop,.groupHead{align-items:flex-start;flex-direction:column}.shellActions{width:100%}.shellActions button{flex:1}.repoControls{width:100%;min-width:0}.choicegrid{display:grid;grid-template-columns:1fr 1fr}.rotatebox.open{grid-template-columns:1fr}}
.juiceHover{outline:3px solid #ed9238;background:#fff1df}.connection[draggable=true]{cursor:grab}.juiceCard{padding:12px;margin-top:10px;border:1px solid var(--line);border-radius:10px}.juiceCard p{margin:6px 0;overflow-wrap:anywhere}
.persimmonsFooter{text-align:center;margin:26px 0 0;color:var(--muted);font-size:12px;line-height:1.5}.persimmonsFooter strong{display:block;color:var(--ink);font-size:13px;margin-bottom:4px}.vaultFlow{font-size:15px;line-height:1.4;opacity:.72}
.vaultSummary{display:flex;align-items:center;gap:10px;margin-bottom:12px}.lockIcon{font-size:22px;line-height:1}.vaultCount{color:var(--muted);font-size:12px}
.credentialSource{display:flex;gap:6px;align-items:baseline;margin-top:10px;color:var(--muted);font-size:12px;overflow-wrap:anywhere}.credentialSource a{color:inherit}.credentialId{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;text-transform:uppercase}
#namedVaultList{display:grid;gap:10px}.namedVaultCard{padding:14px 16px}.namedVaultMeta{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:8px}.namedVaultBadge{display:inline-flex;align-items:center;padding:3px 7px;border:1px solid var(--line);border-radius:999px;color:var(--muted);font-size:11px}.namedVaultActions{display:flex;gap:8px;flex-wrap:wrap;margin-top:12px}.namedVaultBody{margin-top:12px;padding:14px;border:1px dashed var(--line);border-radius:11px;color:var(--muted);font-size:12px;line-height:1.5}.namedVaultBody strong{display:block;color:var(--ink);margin-bottom:3px}
@media(max-width:720px){.vaultSummary{align-items:flex-start}.shellActions .buttonLink,.shellActions button{flex:1}}
</style>
</head>
<body>
<main>
<section class="hero">
<div class="heroInner">
<h1><span class="heroName">Persimmons</span><span class="heroPermissions">permissions</span><span class="heroPromise">put plainly</span></h1>
<div class="heroFlow" aria-label="Orange to water to robot">🍊 → 💧 → 🤖</div>
<h1><span class="heroName"><span class="heroFruit">🍊</span>Persimmons</span><span class="heroPermissions">permissions</span><span class="heroPromise">put plainly</span></h1>
</div>
</section>
<section class="vaultShell">
<div class="shellTop">
<div><h2>Your Persimmons</h2><div class="hint"><span id="userIdentity">Resolving signed-in user…</span></div></div>
<div class="shellActions"><button id="refreshAll">Refresh</button><button id="signOutButton" hidden>Sign out</button><button class="primary" id="addButton">+ Add</button></div>
<div><h2>Master vault</h2><div id="userIdentity" class="hint"></div></div>
<div class="shellActions"><button class="primary" id="addCredential" hidden>+ Add credential</button><button id="signOutButton" hidden>Sign out</button><a id="signInLink" class="buttonLink" href="/signin" hidden>Sign in</a></div>
</div>
<div class="vaultGroup">
<div class="groupHead">
<div><strong>👤 My vault</strong><div class="hint">Available to you across Teahub.</div></div>
</div>
<div class="groupRule" aria-hidden="true"></div>
<div id="userState" class="state">Loading…</div>
<div id="userState" class="state" hidden></div>
<div id="userList" class="list"></div>
</div>
<div class="vaultGroup">
<div class="groupHead">
<div><strong>📦 Repository vaults</strong><div class="hint">Caller-authorized repository secrets.</div></div>
<div class="repoControls"><select id="repoSelect"><option value="">Loading repositories…</option></select></div>
</div>
<div id="repoState" class="state">Discovering writable repositories…</div>
<div id="repoList" class="list"></div>
<div class="vaultGroup" id="namedVaults" hidden>
<div class="groupHead"><div><strong>📦 Vaults</strong><div class="hint">Private spaces for scoped Persimmons.</div></div><button id="newVault" class="primary">+ New vault</button></div>
<div class="groupRule" aria-hidden="true"></div>
<div id="namedVaultList" class="list" aria-live="polite"></div>
</div>
</section>
<footer class="persimmonsFooter"><strong>Passwords, PATs &amp; plenty of other useful P’s.</strong><div class="vaultFlow" aria-label="Orange to water to robot">🍊 → 💧 → 🤖</div></footer>
</main>
<div class="scrim" id="composerScrim" hidden>
<section class="composer" role="dialog" aria-modal="true" aria-labelledby="composerTitle">
<div class="composerTop"><div><div class="stepnum">Add a Persimmon</div><h2 id="composerTitle">Simple now, reusable later.</h2><div class="hint" id="stepSummary">What are you connecting?</div></div><button class="close" id="closeComposer">×</button></div>
<div class="step" id="step1">
<div class="question">What are you connecting?</div>
<div class="choicegrid">
<button class="choice provider" data-provider="Gitea"><strong>Gitea</strong><small>Personal access token</small></button>
<button class="choice provider" data-provider="Cloudflare"><strong>Cloudflare</strong><small>API token</small></button>
<button class="choice provider" data-provider="Fly"><strong>Fly</strong><small>Access token</small></button>
<button class="choice provider" data-provider="Other"><strong>Other</strong><small>Password, key or token</small></button>
</div>
</div>
<div class="step" id="step2" hidden>
<div class="question">Where should it be available?</div>
<div class="choicegrid">
<button class="choice vault" data-vault="user"><strong>👤 My vault</strong><small>Reusable by you across Teahub.</small></button>
<button class="choice vault" data-vault="repository"><strong>📦 A repository</strong><small>Only in that repository context.</small></button>
</div>
<div class="field" id="composerRepoField" hidden style="margin-top:12px"><label>Repository</label><select id="composerRepo"><option value="">Choose a repository…</option></select></div>
</div>
<div class="step" id="step3" hidden>
<div class="question">Name it, then add only what it needs.</div>
<div class="field"><label>Name</label><input id="connectionName" placeholder="e.g. GITEA_TOKEN" autocomplete="off"><div class="fieldHelp">This becomes the Gitea secret name and the Persimmon title.</div></div>
<div class="field"><label id="accountLabel">Account</label><input id="accountInput" placeholder=""></div>
<div class="field" id="typeField" hidden><label>Type</label><select id="typeInput"><option>Password</option><option>PAT</option><option>API key</option><option>Token</option><option>Other</option></select></div>
<div class="field"><label id="valueLabel">Value</label><input id="valueInput" type="password" autocomplete="new-password" spellcheck="false"></div>
<div class="field" id="scopeField"><label>Intended capabilities</label><div class="checks" id="scopeChoices"></div></div>
<details class="advanced"><summary>Advanced</summary><div class="inside">
<div class="field"><label>Expires</label><input id="expiresInput" placeholder="optional"></div>
<div class="field"><label>Notes</label><textarea id="notesInput" placeholder="optional"></textarea></div>
</div></details>
</div>
<div class="state" id="composerState"></div>
<div class="composerNav"><button id="backButton" hidden>Back</button><div class="actions"><button class="primary" id="nextButton">Next</button><button class="primary" id="saveButton" hidden>Save to vault</button></div></div>
</section>
</div>
<script type="module" src="./app.js"></script>
<script type="module" src="/assets/app.js"></script>
</body>
</html>
</html>