Add credential sharing openspec

This commit is contained in:
Anthony Ettinger 2026-06-06 18:47:41 +00:00
parent de517ba9b7
commit a0314eb774
23 changed files with 616 additions and 132 deletions

View file

@ -6,6 +6,8 @@ LOGICSRC_SCHEMA_VERSION=0.1
COINPAY_API_URL= COINPAY_API_URL=
COINPAY_API_KEY= COINPAY_API_KEY=
COINPAY_MERCHANT_ID=
COINPAY_HIRE_US_BLOCKCHAIN=USDC_BASE
COINPAY_WEBHOOK_SECRET= COINPAY_WEBHOOK_SECRET=
UGIG_API_URL= UGIG_API_URL=

View file

@ -4,7 +4,7 @@ LogicSRC is an open standards initiative for human and AI agent coordination, ma
CommandBoard.run is the first hosted product built on LogicSRC: a modern BBS where humans and AI agents coordinate work through boards, tasks, DID identity, OAuth, CLI, TUI, plugins, reputation, audit logs, and payments. CommandBoard.run is the first hosted product built on LogicSRC: a modern BBS where humans and AI agents coordinate work through boards, tasks, DID identity, OAuth, CLI, TUI, plugins, reputation, audit logs, and payments.
The standards surface is named `logicsrc`. Product CLIs can embed it as a sub-command, including `sh1pt logicsrc ...`, so users can choose workflows that only use OpenSpec contracts from LogicSRC. The standards surface is named `logicsrc`. External tools can consume LogicSRC contracts, but the LogicSRC CLI remains the OpenStandards command surface.
## Monorepo ## Monorepo
@ -13,7 +13,7 @@ apps/
commandboard-api REST API reference service commandboard-api REST API reference service
commandboard-web PWA shell commandboard-web PWA shell
packages/ packages/
cli logicsrc OpenSpec CLI, also exposed as commandboard/cb cli logicsrc OpenSpec CLI
logicsrc-mcp @profullstack/logicsrc-mcp standards MCP server logicsrc-mcp @profullstack/logicsrc-mcp standards MCP server
sdk SDK contract types and helpers sdk SDK contract types and helpers
tui terminal UI tui terminal UI
@ -23,7 +23,6 @@ packages/
plugins/ plugins/
coinpay default DID, wallet, payment, and escrow plugin coinpay default DID, wallet, payment, and escrow plugin
ugig default jobs and gigs marketplace plugin ugig default jobs and gigs marketplace plugin
sh1pt default projects, actions, releases, and delivery plugin
docs/ docs/
specs, CLI conventions, permissions, and roadmap notes specs, CLI conventions, permissions, and roadmap notes
scripts/ scripts/
@ -57,7 +56,7 @@ It provides read-only resources for docs and schemas, validation/example tools,
- LogicSRC CLI, SDK, TUI, PWA, MCP, and curl-compatible API conventions. - LogicSRC CLI, SDK, TUI, PWA, MCP, and curl-compatible API conventions.
- CommandBoard.run reference implementation. - CommandBoard.run reference implementation.
- Monorepo-maintained plugin system. - Monorepo-maintained plugin system.
- sh1pt CLI integration through `sh1pt logicsrc ...` with OpenSpec-only mode. - Credential Sharing OpenSpec for .env, Doppler, Railway variables, and GitHub Secrets.
- CoinPay as the default payment, DID, wallet, and escrow plugin. - CoinPay as the default payment, DID, wallet, and escrow plugin.
- uGig as the default jobs and gigs marketplace plugin. - uGig as the default jobs and gigs marketplace plugin.
- Installer, update/upgrade, remove/uninstall workflows. - Installer, update/upgrade, remove/uninstall workflows.

View file

@ -11,7 +11,12 @@ beforeAll(async () => {
accessSync(new URL("../dist/index.html", import.meta.url)); accessSync(new URL("../dist/index.html", import.meta.url));
server = spawn(process.execPath, ["server.js"], { server = spawn(process.execPath, ["server.js"], {
cwd: new URL("..", import.meta.url), cwd: new URL("..", import.meta.url),
env: { ...process.env, PORT: String(port) } env: {
...process.env,
PORT: String(port),
COINPAY_API_KEY: "",
COINPAY_API_URL: "https://coinpayportal.example"
}
}); });
await waitForServer(); await waitForServer();
@ -23,7 +28,7 @@ afterAll(() => {
describe("LogicSRC web contracts", () => { describe("LogicSRC web contracts", () => {
it("serves SPA routes from the built app shell", async () => { it("serves SPA routes from the built app shell", async () => {
for (const route of ["/", "/openspec", "/docs", "/blog", "/hire-us", "/about", "/terms", "/privacy"]) { for (const route of ["/", "/openspec", "/credential-sharing", "/docs", "/blog", "/hire-us", "/about", "/terms", "/privacy"]) {
const response = await fetch(`${baseUrl}${route}`); const response = await fetch(`${baseUrl}${route}`);
const text = await response.text(); const text = await response.text();
@ -41,6 +46,7 @@ describe("LogicSRC web contracts", () => {
expect(response.headers.get("content-type")).toContain("application/xml"); expect(response.headers.get("content-type")).toContain("application/xml");
expect(response.headers.get("cache-control")).toBe("no-store"); expect(response.headers.get("cache-control")).toBe("no-store");
expect(text).toContain("<loc>https://logicsrc.com/openspec</loc>"); expect(text).toContain("<loc>https://logicsrc.com/openspec</loc>");
expect(text).toContain("<loc>https://logicsrc.com/credential-sharing</loc>");
expect(text).toContain("<loc>https://logicsrc.com/hire-us</loc>"); expect(text).toContain("<loc>https://logicsrc.com/hire-us</loc>");
expect(text).toContain("<loc>https://logicsrc.com/blog</loc>"); expect(text).toContain("<loc>https://logicsrc.com/blog</loc>");
}); });
@ -54,6 +60,20 @@ describe("LogicSRC web contracts", () => {
expect(response.headers.get("cache-control")).toBe("no-store"); expect(response.headers.get("cache-control")).toBe("no-store");
expect(text).toContain("<rss version=\"2.0\""); expect(text).toContain("<rss version=\"2.0\"");
expect(text).toContain("<title>LogicSRC OpenSpec Compatibility</title>"); expect(text).toContain("<title>LogicSRC OpenSpec Compatibility</title>");
expect(text).toContain("<title>LogicSRC Credential Sharing OpenSpec</title>");
});
it("does not create CoinPay checkout without server credentials", async () => {
const response = await fetch(`${baseUrl}/api/hire-us/coinpay-checkout`, {
method: "POST",
headers: { "content-type": "application/json" },
body: "{}"
});
const body = await response.json();
expect(response.status).toBe(503);
expect(response.headers.get("cache-control")).toBe("no-store");
expect(body).toEqual({ success: false, error: "CoinPay checkout is not configured" });
}); });
}); });

View file

@ -12,12 +12,25 @@ test.describe("LogicSRC PWA", () => {
await expect(page.getByText("openspec export")).toBeVisible(); await expect(page.getByText("openspec export")).toBeVisible();
}); });
test("renders Credential Sharing OpenSpec route", async ({ page }) => {
await page.goto("/credential-sharing");
await expect(page.getByRole("heading", { name: "Credential Sharing", exact: true })).toBeVisible();
await expect(page.getByText("Open replacement architecture for secrets")).toBeVisible();
await expect(page.getByRole("heading", { name: ".env", exact: true })).toBeVisible();
await expect(page.getByRole("heading", { name: "Doppler", exact: true })).toBeVisible();
await expect(page.getByRole("heading", { name: "Railway", exact: true })).toBeVisible();
await expect(page.getByRole("heading", { name: "GitHub Secrets", exact: true })).toBeVisible();
await expect(page.getByText("logicsrc credentials plan --from env --to railway")).toBeVisible();
});
test("renders top-level docs and legal route targets", async ({ page }) => { test("renders top-level docs and legal route targets", async ({ page }) => {
await page.goto("/privacy"); await page.goto("/privacy");
await expect(page.getByRole("heading", { name: "Top-Level Pages" })).toBeVisible(); await expect(page.getByRole("heading", { name: "Top-Level Pages" })).toBeVisible();
await expect(page.getByText("/docs · Docs")).toBeVisible(); await expect(page.getByText("/docs · Docs")).toBeVisible();
await expect(page.getByText("/blog · Blog")).toBeVisible(); await expect(page.getByText("/blog · Blog")).toBeVisible();
await expect(page.getByText("/credential-sharing · Credential Sharing")).toBeVisible();
await expect(page.getByText("/terms · Terms")).toBeVisible(); await expect(page.getByText("/terms · Terms")).toBeVisible();
await expect(page.getByText("/privacy · Privacy")).toBeVisible(); await expect(page.getByText("/privacy · Privacy")).toBeVisible();
}); });
@ -29,7 +42,8 @@ test.describe("LogicSRC PWA", () => {
await expect(page.locator(".price-row strong", { hasText: "$500" })).toBeVisible(); await expect(page.locator(".price-row strong", { hasText: "$500" })).toBeVisible();
await expect(page.getByText("per week")).toBeVisible(); await expect(page.getByText("per week")).toBeVisible();
await expect(page.getByText("open infrastructure and open specs for AI agent systems")).toBeVisible(); await expect(page.getByText("open infrastructure and open specs for AI agent systems")).toBeVisible();
await expect(page.getByRole("link", { name: "Request CoinPay invoice" })).toHaveAttribute("href", /CoinPay/); await expect(page.getByRole("button", { name: "Pay with CoinPay" })).toBeVisible();
await expect(page.getByText("without exposing merchant credentials to the browser")).toBeVisible();
await expect(page.getByText("COINPAY_PRODUCT=logicsrc-hire-us")).toBeVisible(); await expect(page.getByText("COINPAY_PRODUCT=logicsrc-hire-us")).toBeVisible();
}); });
@ -40,10 +54,12 @@ test.describe("LogicSRC PWA", () => {
expect(sitemap.status()).toBe(200); expect(sitemap.status()).toBe(200);
expect(sitemap.headers()["content-type"]).toMatch(/(?:application|text)\/xml/); expect(sitemap.headers()["content-type"]).toMatch(/(?:application|text)\/xml/);
await expect(sitemap.text()).resolves.toContain("https://logicsrc.com/openspec"); await expect(sitemap.text()).resolves.toContain("https://logicsrc.com/openspec");
await expect(sitemap.text()).resolves.toContain("https://logicsrc.com/credential-sharing");
await expect(sitemap.text()).resolves.toContain("https://logicsrc.com/hire-us"); await expect(sitemap.text()).resolves.toContain("https://logicsrc.com/hire-us");
expect(rss.status()).toBe(200); expect(rss.status()).toBe(200);
expect(rss.headers()["content-type"]).toMatch(/(?:application|text)\/xml/); expect(rss.headers()["content-type"]).toMatch(/(?:application|text)\/xml/);
await expect(rss.text()).resolves.toContain("LogicSRC OpenSpec Compatibility"); await expect(rss.text()).resolves.toContain("LogicSRC OpenSpec Compatibility");
await expect(rss.text()).resolves.toContain("LogicSRC Credential Sharing OpenSpec");
}); });
}); });

View file

@ -13,5 +13,12 @@
<description>LogicSRC adds an OpenSpec.dev comparison and compatibility mode for repo-local specs, proposals, tasks, and deltas.</description> <description>LogicSRC adds an OpenSpec.dev comparison and compatibility mode for repo-local specs, proposals, tasks, and deltas.</description>
<pubDate>Sat, 06 Jun 2026 00:00:00 GMT</pubDate> <pubDate>Sat, 06 Jun 2026 00:00:00 GMT</pubDate>
</item> </item>
<item>
<title>LogicSRC Credential Sharing OpenSpec</title>
<link>https://logicsrc.com/credential-sharing</link>
<guid>https://logicsrc.com/credential-sharing</guid>
<description>LogicSRC adds a credential-sharing OpenSpec for .env, Doppler, Railway variables, GitHub Secrets, and future provider adapters.</description>
<pubDate>Sat, 06 Jun 2026 00:00:00 GMT</pubDate>
</item>
</channel> </channel>
</rss> </rss>

View file

@ -25,6 +25,11 @@
<changefreq>weekly</changefreq> <changefreq>weekly</changefreq>
<priority>0.8</priority> <priority>0.8</priority>
</url> </url>
<url>
<loc>https://logicsrc.com/credential-sharing</loc>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url> <url>
<loc>https://logicsrc.com/hire-us</loc> <loc>https://logicsrc.com/hire-us</loc>
<changefreq>weekly</changefreq> <changefreq>weekly</changefreq>

View file

@ -25,6 +25,11 @@ const mimeTypes = {
createServer((request, response) => { createServer((request, response) => {
const url = new URL(request.url ?? "/", `http://${request.headers.host ?? "localhost"}`); const url = new URL(request.url ?? "/", `http://${request.headers.host ?? "localhost"}`);
if (url.pathname === "/api/hire-us/coinpay-checkout") {
handleHireUsCoinPayCheckout(request, response);
return;
}
if (url.pathname === "/health" || url.pathname.startsWith("/api/")) { if (url.pathname === "/health" || url.pathname.startsWith("/api/")) {
apiServer.emit("request", request, response); apiServer.emit("request", request, response);
return; return;
@ -88,3 +93,112 @@ function sendFile(file, headOnly, response) {
createReadStream(file).pipe(response); createReadStream(file).pipe(response);
} }
async function handleHireUsCoinPayCheckout(request, response) {
if (request.method !== "POST") {
sendJson(response, 405, { success: false, error: "Method not allowed" }, { allow: "POST" });
return;
}
const apiKey = process.env.COINPAY_API_KEY;
const merchantId = process.env.COINPAY_MERCHANT_ID;
const apiUrl = process.env.COINPAY_API_URL || "https://coinpayportal.com";
const blockchain = process.env.COINPAY_HIRE_US_BLOCKCHAIN || "USDC_BASE";
if (!apiKey) {
sendJson(response, 503, { success: false, error: "CoinPay checkout is not configured" });
return;
}
try {
const body = await readJson(request);
const buyerEmail = typeof body.email === "string" ? body.email.trim().slice(0, 160) : "";
const checkoutResponse = await fetch(new URL("/api/payments/create", apiUrl), {
method: "POST",
headers: {
authorization: `Bearer ${apiKey}`,
"content-type": "application/json"
},
body: JSON.stringify({
amount: 500,
currency: "USD",
blockchain,
description: "LogicSRC Hire Us - $500/week",
metadata: {
product: "logicsrc-hire-us",
interval: "week",
source: "logicsrc.com/hire-us",
...(merchantId ? { merchant_id: merchantId } : {}),
...(buyerEmail ? { buyer_email: buyerEmail } : {})
},
redirect_url: `${process.env.PUBLIC_URL || "https://logicsrc.com"}/hire-us?payment=coinpay`
})
});
const payload = await checkoutResponse.json().catch(() => ({}));
if (!checkoutResponse.ok || !payload.success) {
sendJson(response, checkoutResponse.ok ? 502 : checkoutResponse.status, {
success: false,
error: payload.error || "CoinPay checkout failed"
});
return;
}
const payment = payload.payment || {};
sendJson(response, 201, {
success: true,
payment: {
id: payment.id,
amount_usd: Number(payment.amount_usd ?? payment.amount ?? 500),
currency: payment.currency ?? payment.blockchain ?? blockchain,
crypto_amount: payment.amount_crypto ?? payment.crypto_amount ?? null,
address: payment.payment_address ?? null,
qr_code: payment.qr_code ?? null,
expires_at: payment.expires_at ?? null,
status: payment.status ?? "pending",
checkout_url: payment.stripe_checkout_url ?? null
}
});
} catch (error) {
sendJson(response, 500, {
success: false,
error: error instanceof Error ? error.message : "Unable to create CoinPay checkout"
});
}
}
function readJson(request) {
return new Promise((resolve, reject) => {
let body = "";
request.setEncoding("utf8");
request.on("data", (chunk) => {
body += chunk;
if (body.length > 4096) {
reject(new Error("Request body too large"));
request.destroy();
}
});
request.on("end", () => {
if (!body.trim()) {
resolve({});
return;
}
try {
resolve(JSON.parse(body));
} catch {
reject(new Error("Invalid JSON"));
}
});
request.on("error", reject);
});
}
function sendJson(response, status, body, headers = {}) {
response.writeHead(status, {
"cache-control": "no-store",
"content-type": "application/json; charset=utf-8",
...headers
});
response.end(JSON.stringify(body));
}

View file

@ -17,12 +17,11 @@ const schemas = [
]; ];
const implementations = [ const implementations = [
{ name: "CommandBoard.run", detail: "Hosted reference product implementing the LogicSRC primitives." }, { name: "LogicSRC CLI", detail: "`logicsrc` is the canonical OpenStandards CLI for schemas, specs, plugins, and audits." },
{ name: "CLI and TUI", detail: "`logicsrc` is the standards CLI; `commandboard` and `cb` remain compatible product aliases." }, { name: "TUI and PWA", detail: "Terminal and browser reference surfaces mirror the same open contracts." },
{ name: "SDKs", detail: "`@logicsrc/sdk` defines contract types now; Rust, Bun, Node, Python, and curl surfaces mirror the same resources." }, { name: "SDKs", detail: "`@logicsrc/sdk` defines contract types now; Rust, Bun, Node, Python, and curl surfaces mirror the same resources." },
{ name: "sh1pt CLI", detail: "`sh1pt logicsrc ...` lets sh1pt users choose LogicSRC OpenSpec-only workflows." },
{ name: "Reference API", detail: "Sample REST API available under `/api/*` for contract testing." }, { name: "Reference API", detail: "Sample REST API available under `/api/*` for contract testing." },
{ name: "Plugins", detail: "CoinPay, uGig, and sh1pt adapters prove the plugin manifest shape." } { name: "Plugins", detail: "Open plugin contracts let external products consume LogicSRC without LogicSRC calling proprietary tools." }
]; ];
const upcoming = [ const upcoming = [
@ -39,9 +38,23 @@ const agentByteSurfaces = [
{ name: "PWA", detail: "Plan builder, candidate intake, live screening room, artifact review, and decision packet." } { name: "PWA", detail: "Plan builder, candidate intake, live screening room, artifact review, and decision packet." }
]; ];
const credentialProviders = [
{ name: ".env", detail: "Parse, diff, redact, and write local env files without leaking values into logs." },
{ name: "Doppler", detail: "Sync project/config scoped secrets through provider adapters and auditable key fingerprints." },
{ name: "Railway", detail: "Read and write service variables as a deployment target with explicit approval gates." },
{ name: "GitHub Secrets", detail: "Manage repo, organization, and environment secrets through provider-neutral operations." }
];
const credentialSurfaces = [
{ name: "CLI", detail: "`logicsrc credentials` for provider listing, dry-run plans, diffs, approvals, sync, and audit exports." },
{ name: "TUI", detail: "Review key diffs, target providers, approval prompts, fingerprints, and failure states without showing raw secrets." },
{ name: "SDKs", detail: "Rust, Bun, Node, Python, and curl APIs share the same credential source, target, policy, and audit objects." },
{ name: "PWA", detail: "Provider connection health, dry-run previews, approval history, and redacted sync evidence." }
];
const hireUsWork = [ const hireUsWork = [
{ name: "AI agent workflow specs", detail: "Open schemas, repo-local plans, AgentSwarm flows, AgentByte screening contracts, and MCP resources." }, { name: "AI agent workflow specs", detail: "Open schemas, repo-local plans, AgentSwarm flows, AgentByte screening contracts, and MCP resources." },
{ name: "Reference implementations", detail: "CLI, TUI, SDK, PWA, API, curl, and sh1pt-compatible surfaces that prove the spec can be used." }, { name: "Reference implementations", detail: "CLI, TUI, SDK, PWA, API, curl, and provider-neutral plugin surfaces that prove the spec can be used." },
{ name: "Integration hardening", detail: "GitHub, CoinPay, model providers, webhooks, audit logs, permissions, and deployment-ready contracts." }, { name: "Integration hardening", detail: "GitHub, CoinPay, model providers, webhooks, audit logs, permissions, and deployment-ready contracts." },
{ name: "Open infrastructure", detail: "Portable code and specs first: no closed workflow lock-in, no one-off agent scripts that cannot be audited." } { name: "Open infrastructure", detail: "Portable code and specs first: no closed workflow lock-in, no one-off agent scripts that cannot be audited." }
]; ];
@ -50,6 +63,7 @@ const pages = [
{ id: "docs", title: "Docs", detail: "Specification guides, CLI conventions, schemas, plugin contracts, SDK conventions, and MCP resources." }, { id: "docs", title: "Docs", detail: "Specification guides, CLI conventions, schemas, plugin contracts, SDK conventions, and MCP resources." },
{ id: "blog", title: "Blog", detail: "Project notes for LogicSRC, AgentSwarm, AgentByte, OpenSpec workflows, and reference implementations." }, { id: "blog", title: "Blog", detail: "Project notes for LogicSRC, AgentSwarm, AgentByte, OpenSpec workflows, and reference implementations." },
{ id: "openspec", title: "OpenSpec", detail: "Comparison and compatibility notes for OpenSpec.dev-style repo-local specs, proposals, tasks, and deltas." }, { id: "openspec", title: "OpenSpec", detail: "Comparison and compatibility notes for OpenSpec.dev-style repo-local specs, proposals, tasks, and deltas." },
{ id: "credential-sharing", title: "Credential Sharing", detail: "Open replacement architecture for portable secret sync across .env, Doppler, Railway variables, GitHub Secrets, and future providers." },
{ id: "hire-us", title: "Hire Us", detail: "$500/week LogicSRC work on open infrastructure, specs, AI agent workflows, and reference implementations paid through CoinPay." }, { id: "hire-us", title: "Hire Us", detail: "$500/week LogicSRC work on open infrastructure, specs, AI agent workflows, and reference implementations paid through CoinPay." },
{ id: "about", title: "About", detail: "LogicSRC is the Profullstack open specification project for human and AI agent coordination." }, { id: "about", title: "About", detail: "LogicSRC is the Profullstack open specification project for human and AI agent coordination." },
{ id: "terms", title: "Terms", detail: "Draft terms will cover acceptable use, reference implementation boundaries, and hosted-product responsibilities." }, { id: "terms", title: "Terms", detail: "Draft terms will cover acceptable use, reference implementation boundaries, and hosted-product responsibilities." },
@ -74,7 +88,7 @@ const comparisonRows = [
}, },
{ {
area: "CLI", area: "CLI",
logicsrc: "`logicsrc`, `commandboard`, `cb`, and `sh1pt logicsrc ...`.", logicsrc: "`logicsrc` as the canonical OpenStandards CLI.",
openspec: "`@fission-ai/openspec` plus native coding-tool slash command integrations." openspec: "`@fission-ai/openspec` plus native coding-tool slash command integrations."
}, },
{ {
@ -104,6 +118,7 @@ document.querySelector<HTMLDivElement>("#app")!.innerHTML = `
<a href="#schemas">Schemas</a> <a href="#schemas">Schemas</a>
<a href="/agent-swarm">Soon</a> <a href="/agent-swarm">Soon</a>
<a href="/agentbyte">AgentByte</a> <a href="/agentbyte">AgentByte</a>
<a href="/credential-sharing">Credentials</a>
<a href="#cli">CLI</a> <a href="#cli">CLI</a>
<a href="/docs">Docs</a> <a href="/docs">Docs</a>
<a href="/blog">Blog</a> <a href="/blog">Blog</a>
@ -218,14 +233,44 @@ logicsrc agentbyte session audit \\
<pre><code>npm install <pre><code>npm install
npm run schemas:validate npm run schemas:validate
npm --workspace @logicsrc/cli run dev -- \\ npm --workspace @logicsrc/cli run dev -- \\
--openspec-only task validate ./task.yaml
sh1pt logicsrc --openspec-only \\
task validate ./task.yaml</code></pre> task validate ./task.yaml</code></pre>
<p>The CLI belongs here as standards tooling: validate schemas, inspect objects, drive SDK/TUI/PWA/MCP contracts, and exercise compatible implementations.</p> <p>The CLI belongs here as standards tooling: validate schemas, inspect objects, drive SDK/TUI/PWA/MCP contracts, and exercise compatible implementations.</p>
</div> </div>
</section> </section>
<section id="credential-sharing" class="band coming-soon credentials">
<div class="section-head">
<h2>Credential Sharing</h2>
<p>A coming-soon LogicSRC OpenSpec for replacing closed credential-sharing workflows with auditable, provider-neutral secret sync.</p>
</div>
<div class="soon-layout">
<article class="soon-lead">
<span>slug: credential-sharing</span>
<h3>Open replacement architecture for secrets</h3>
<p>LogicSRC defines the credential source, target, diff, approval, sync, rollback, and audit objects. External tools can consume the contract, but LogicSRC remains the open standards CLI and does not call out to proprietary product commands.</p>
<pre><code>logicsrc credentials providers
logicsrc credentials plan --from env --to railway
logicsrc credentials plan --from doppler --to github-secrets</code></pre>
</article>
<div class="soon-grid">
${credentialProviders.map((item) => `
<article>
<h3>${item.name}</h3>
<p>${item.detail}</p>
</article>
`).join("")}
</div>
</div>
<div class="surface-strip" aria-label="Credential sharing reference surfaces">
${credentialSurfaces.map((item) => `
<article>
<h3>${item.name}</h3>
<p>${item.detail}</p>
</article>
`).join("")}
</div>
</section>
<section id="openspec" class="band"> <section id="openspec" class="band">
<div class="section-head"> <div class="section-head">
<h2>LogicSRC vs OpenSpec.dev</h2> <h2>LogicSRC vs OpenSpec.dev</h2>
@ -248,10 +293,7 @@ sh1pt logicsrc --openspec-only \\
<div class="cli-panel compare-note"> <div class="cli-panel compare-note">
<h2>Compatibility Mode</h2> <h2>Compatibility Mode</h2>
<pre><code>logicsrc --openspec agentswarm --yolo \\ <pre><code>logicsrc --openspec agentswarm --yolo \\
--repo profullstack/logicsrc --repo profullstack/logicsrc</code></pre>
sh1pt logicsrc --openspec \\
agentswarm --yolo</code></pre>
<p><code>--openspec</code> enables OpenSpec.dev-compatible repo-local specs, proposals, tasks, and deltas where supported. <code>openspec import</code> and <code>openspec export</code> summarize those artifacts for LogicSRC workflows. <code>--openspec-only</code> restricts work to LogicSRC-published contracts.</p> <p><code>--openspec</code> enables OpenSpec.dev-compatible repo-local specs, proposals, tasks, and deltas where supported. <code>openspec import</code> and <code>openspec export</code> summarize those artifacts for LogicSRC workflows. <code>--openspec-only</code> restricts work to LogicSRC-published contracts.</p>
</div> </div>
</section> </section>
@ -283,15 +325,16 @@ sh1pt logicsrc --openspec \\
<article class="hire-panel"> <article class="hire-panel">
<p class="eyebrow">Profullstack standards work</p> <p class="eyebrow">Profullstack standards work</p>
<h3>Open-spec AI agent implementation help</h3> <h3>Open-spec AI agent implementation help</h3>
<p>Hire us to turn agent ideas into portable LogicSRC specs, CLIs, SDKs, MCP resources, PWAs, APIs, and sh1pt-compatible workflows. We prioritize auditable contracts, repo-local artifacts, and integrations that can move between model providers and infrastructure.</p> <p>Hire us to turn agent ideas into portable LogicSRC specs, CLIs, SDKs, MCP resources, PWAs, APIs, and provider-neutral plugin workflows. We prioritize auditable contracts, repo-local artifacts, and integrations that can move between model providers and infrastructure.</p>
<div class="price-row"> <div class="price-row">
<strong>$500</strong> <strong>$500</strong>
<span>per week</span> <span>per week</span>
</div> </div>
<div class="cta-row"> <div class="cta-row">
<a class="button-primary" href="mailto:hire-us@profullstack.com?subject=LogicSRC%20Hire%20Us%20-%20CoinPay%20%24500%2Fweek">Request CoinPay invoice</a> <button id="coinpay-checkout-button" class="button-primary" type="button">Pay with CoinPay</button>
<a class="button-secondary" href="/docs">Read specs</a> <a class="button-secondary" href="/docs">Read specs</a>
</div> </div>
<div id="coinpay-result" class="coinpay-result" aria-live="polite"></div>
</article> </article>
<div class="hire-stack"> <div class="hire-stack">
<div class="hire-grid"> <div class="hire-grid">
@ -304,7 +347,7 @@ sh1pt logicsrc --openspec \\
</div> </div>
<article id="coinpay-setup" class="coinpay-panel"> <article id="coinpay-setup" class="coinpay-panel">
<h3>CoinPay checkout hook</h3> <h3>CoinPay checkout hook</h3>
<p>Once the CoinPay org is configured, this page can point the primary CTA at a hosted checkout or escrow request for the weekly plan.</p> <p>The primary CTA creates a CoinPay payment request for the weekly plan without exposing merchant credentials to the browser.</p>
<pre><code>COINPAY_ORG=profullstack <pre><code>COINPAY_ORG=profullstack
COINPAY_PRODUCT=logicsrc-hire-us COINPAY_PRODUCT=logicsrc-hire-us
COINPAY_AMOUNT_USD=500 COINPAY_AMOUNT_USD=500
@ -341,6 +384,97 @@ if ("serviceWorker" in navigator) {
}); });
} }
document.querySelector<HTMLButtonElement>("#coinpay-checkout-button")?.addEventListener("click", async () => {
const button = document.querySelector<HTMLButtonElement>("#coinpay-checkout-button");
const result = document.querySelector<HTMLDivElement>("#coinpay-result");
if (!button || !result) return;
button.disabled = true;
button.textContent = "Creating payment...";
result.replaceChildren(buildParagraph("Creating CoinPay payment request."));
try {
const response = await fetch("/api/hire-us/coinpay-checkout", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({})
});
const payload = await response.json();
if (!response.ok || !payload.success) {
throw new Error(payload.error || "CoinPay payment could not be created.");
}
const payment = payload.payment;
if (payment.checkout_url) {
window.location.href = payment.checkout_url;
return;
}
result.replaceChildren(buildCoinPayResult(payment));
} catch (error) {
result.replaceChildren(
buildParagraph(error instanceof Error ? error.message : "CoinPay payment could not be created.")
);
} finally {
button.disabled = false;
button.textContent = "Pay with CoinPay";
}
});
function buildCoinPayResult(payment: {
amount_usd?: number;
crypto_amount?: string | null;
currency?: string;
address?: string | null;
id?: string;
qr_code?: string | null;
}) {
const fragment = document.createDocumentFragment();
const heading = document.createElement("strong");
heading.textContent = "CoinPay payment ready";
fragment.append(heading);
const details = document.createElement("dl");
details.append(
buildDetail("Amount", `$${payment.amount_usd ?? 500} / ${payment.crypto_amount ?? "quoted at checkout"} ${payment.currency ?? "USDC_BASE"}`),
buildDetail("Address", payment.address ?? "Open CoinPay to complete payment", true),
buildDetail("Payment ID", payment.id ?? "pending", true)
);
fragment.append(details);
if (payment.qr_code) {
const image = document.createElement("img");
image.src = payment.qr_code;
image.alt = "CoinPay payment QR code";
fragment.append(image);
}
return fragment;
}
function buildDetail(label: string, value: string, code = false) {
const row = document.createElement("div");
const term = document.createElement("dt");
const definition = document.createElement("dd");
term.textContent = label;
if (code) {
const codeElement = document.createElement("code");
codeElement.textContent = value;
definition.append(codeElement);
} else {
definition.textContent = value;
}
row.append(term, definition);
return row;
}
function buildParagraph(text: string) {
const paragraph = document.createElement("p");
paragraph.textContent = text;
return paragraph;
}
if (window.location.pathname === "/agent-swarm") { if (window.location.pathname === "/agent-swarm") {
document.querySelector("#agent-swarm")?.scrollIntoView(); document.querySelector("#agent-swarm")?.scrollIntoView();
} }
@ -350,6 +484,6 @@ if (window.location.pathname === "/agentbyte") {
} }
const pageRoute = window.location.pathname.slice(1); const pageRoute = window.location.pathname.slice(1);
if (["docs", "blog", "openspec", "hire-us", "about", "terms", "privacy"].includes(pageRoute)) { if (["docs", "blog", "openspec", "credential-sharing", "hire-us", "about", "terms", "privacy"].includes(pageRoute)) {
document.querySelector(`#${pageRoute}`)?.scrollIntoView(); document.querySelector(`#${pageRoute}`)?.scrollIntoView();
} }

View file

@ -19,6 +19,17 @@ a {
text-decoration: none; text-decoration: none;
} }
button {
border: 0;
font: inherit;
cursor: pointer;
}
button:disabled {
cursor: wait;
opacity: 0.72;
}
.shell { .shell {
display: grid; display: grid;
grid-template-columns: 16rem minmax(0, 1fr); grid-template-columns: 16rem minmax(0, 1fr);
@ -236,11 +247,20 @@ h1 {
background: #f7f3e8; background: #f7f3e8;
} }
.credentials .soon-lead {
background: #eef3f7;
}
.agentbyte .soon-lead span { .agentbyte .soon-lead span {
border-color: #e3c878; border-color: #e3c878;
color: #735b14; color: #735b14;
} }
.credentials .soon-lead span {
border-color: #9fc3da;
color: #225d77;
}
.soon-lead span { .soon-lead span {
display: inline-block; display: inline-block;
margin-bottom: 0.75rem; margin-bottom: 0.75rem;
@ -284,6 +304,32 @@ h1 {
line-height: 1.45; line-height: 1.45;
} }
.surface-strip {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 0.75rem;
margin-top: 0.75rem;
}
.surface-strip article {
min-height: 7.25rem;
padding: 0.85rem;
border: 1px solid #d6ddd2;
border-radius: 8px;
background: #ffffff;
}
.surface-strip h3 {
margin-bottom: 0.35rem;
font-size: 1rem;
}
.surface-strip p {
margin-bottom: 0;
color: #58615b;
line-height: 1.45;
}
.schema-list { .schema-list {
display: grid; display: grid;
gap: 0.5rem; gap: 0.5rem;
@ -485,10 +531,61 @@ pre {
margin-bottom: 0; margin-bottom: 0;
} }
.coinpay-result {
margin-top: 0.85rem;
color: #ccd5ce;
}
.coinpay-result:empty {
display: none;
}
.coinpay-result strong {
display: block;
margin-bottom: 0.5rem;
color: #ffffff;
}
.coinpay-result p {
margin-bottom: 0;
}
.coinpay-result dl {
display: grid;
gap: 0.45rem;
margin: 0;
}
.coinpay-result div {
display: grid;
gap: 0.15rem;
}
.coinpay-result dt {
color: #8ee4c9;
font-size: 0.8rem;
font-weight: 800;
text-transform: uppercase;
}
.coinpay-result dd {
margin: 0;
overflow-wrap: anywhere;
}
.coinpay-result img {
width: min(12rem, 100%);
height: auto;
margin-top: 0.75rem;
border-radius: 6px;
background: #ffffff;
}
@media (max-width: 980px) { @media (max-width: 980px) {
.primitive-grid, .primitive-grid,
.implementation-list, .implementation-list,
.hire-grid { .hire-grid,
.surface-strip {
grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-columns: repeat(2, minmax(0, 1fr));
} }
@ -531,7 +628,8 @@ pre {
.primitive-grid, .primitive-grid,
.soon-grid, .soon-grid,
.implementation-list, .implementation-list,
.hire-grid { .hire-grid,
.surface-strip {
grid-template-columns: 1fr; grid-template-columns: 1fr;
} }

View file

@ -10,19 +10,9 @@ Aliases:
```bash ```bash
logicsrc logicsrc
commandboard
cb
``` ```
`logicsrc` is the canonical standards CLI. `commandboard` and `cb` remain product/client aliases for CommandBoard.run-compatible workflows. `logicsrc` is the canonical standards CLI.
Product CLIs may embed LogicSRC as a sub-command:
```bash
sh1pt logicsrc <resource> <action> [options]
sh1pt logicsrc --openspec <resource> <action> [options]
sh1pt logicsrc --openspec-only <resource> <action> [options]
```
`--openspec` enables OpenSpec.dev-compatible repo-local planning conventions where supported, such as specs, proposals, implementation tasks, and requirement deltas. `--openspec` enables OpenSpec.dev-compatible repo-local planning conventions where supported, such as specs, proposals, implementation tasks, and requirement deltas.
@ -41,6 +31,7 @@ task
wallet wallet
events events
agentswarm agentswarm
credentials
openspec openspec
plugins plugins
tui tui
@ -53,7 +44,6 @@ AgentSwarm master-agent command:
```bash ```bash
logicsrc agentswarm --yolo --repo profullstack/logicsrc --agents reproduce,patch,review logicsrc agentswarm --yolo --repo profullstack/logicsrc --agents reproduce,patch,review
logicsrc --openspec agentswarm --yolo --repo profullstack/logicsrc logicsrc --openspec agentswarm --yolo --repo profullstack/logicsrc
sh1pt logicsrc --openspec-only agentswarm --yolo --repo profullstack/logicsrc
``` ```
`agentswarm --yolo` opens the master agent flow. The master agent coordinates slave agents for scoped work such as reproduction, patching, review, documentation, and release evidence. `agentswarm --yolo` opens the master agent flow. The master agent coordinates slave agents for scoped work such as reproduction, patching, review, documentation, and release evidence.
@ -66,6 +56,16 @@ logicsrc openspec export --out logicsrc-openspec-summary.md
logicsrc openspec change --id add-agent-policy --capability agents logicsrc openspec change --id add-agent-policy --capability agents
``` ```
Credential sharing commands:
```bash
logicsrc credentials providers
logicsrc credentials plan --from env --to railway
logicsrc credentials plan --from doppler --to github-secrets
```
Credential sharing is provider-neutral. External tools can consume LogicSRC credential contracts, but LogicSRC commands do not call proprietary product CLIs.
When `--openspec` is enabled, AgentSwarm writes OpenSpec.dev-style files under `openspec/changes/<change-id>/`. When `--openspec` is enabled, AgentSwarm writes OpenSpec.dev-style files under `openspec/changes/<change-id>/`.
Machine-readable output should be available anywhere data is returned: Machine-readable output should be available anywhere data is returned:

114
docs/credential-sharing.md Normal file
View file

@ -0,0 +1,114 @@
# Credential Sharing OpenSpec
Status: coming soon
Slug: `credential-sharing`
Credential Sharing is a LogicSRC OpenSpec for portable, auditable secret synchronization across local files and infrastructure providers. It is intended to replace closed, proprietary credential-sharing workflows with a provider-neutral contract.
LogicSRC defines the open objects, CLI commands, SDK calls, TUI states, PWA states, provider adapter capabilities, and audit records. External products may consume this contract, but LogicSRC does not call out to product-specific commands.
## First Providers
```txt
env
doppler
railway
github-secrets
```
- `.env`: read, diff, redact, and write local environment files.
- Doppler: sync project/config scoped secrets.
- Railway: sync service variables.
- GitHub Secrets: sync repository, organization, and environment secrets.
## Core Objects
```txt
credential_provider
credential_source
credential_target
credential_key
credential_fingerprint
credential_policy
credential_diff
credential_sync_plan
credential_sync_run
credential_approval
credential_rollback
credential_audit_event
```
## CLI Spec
Command namespace:
```bash
logicsrc credentials <command>
```
Required commands:
```txt
providers
inspect
plan
diff
approve
sync
rollback
audit
export
```
Examples:
```bash
logicsrc credentials providers
logicsrc credentials plan --from env --to railway
logicsrc credentials plan --from doppler --to github-secrets
logicsrc credentials diff --from env --to doppler --redact
logicsrc credentials sync --plan cred_plan_123 --approve
logicsrc credentials audit --run cred_run_123 --format markdown
```
## Security Rules
- Raw secret values must never be printed by default.
- Audit logs should store key names, targets, timestamps, actor identity, and value fingerprints, not raw values.
- Every write operation should support dry-run mode.
- Provider adapters must declare read/write capabilities before a plan is generated.
- Destructive changes require explicit approval.
- Rollbacks must be represented as new sync plans rather than hidden mutation history.
## SDK Spec
All SDKs should expose the same conceptual API:
```txt
listCredentialProviders()
inspectCredentialSource(source)
createCredentialSyncPlan(input)
diffCredentialTargets(planId)
approveCredentialSync(planId, approval)
runCredentialSync(planId)
rollbackCredentialSync(runId)
exportCredentialAudit(runId)
```
## Provider Adapter Contract
Provider adapters implement the LogicSRC credential provider contract:
```txt
provider.id
provider.capabilities
provider.auth_requirements
provider.inspect()
provider.diff()
provider.write()
provider.rollback()
provider.audit()
```
The adapter boundary lets tools such as a PWA, TUI, CI workflow, or external CLI consume the same open standard without making LogicSRC depend on any specific product.

View file

@ -1,10 +1,10 @@
openapi: 3.1.0 openapi: 3.1.0
info: info:
title: CommandBoard.run LogicSRC API title: LogicSRC Reference API
version: 0.1.0 version: 0.1.0
description: REST API draft for the CommandBoard.run reference implementation. description: REST API draft for LogicSRC open standards reference implementations.
servers: servers:
- url: https://commandboard.run - url: https://logicsrc.com
paths: paths:
/api/boards: /api/boards:
get: get:
@ -31,18 +31,18 @@ paths:
responses: responses:
"200": "200":
description: Plugins returned description: Plugins returned
/api/plugins/sh1pt/projects: /api/credentials/providers:
get: get:
summary: List or sync sh1pt projects summary: List supported credential provider targets
responses: responses:
"200": "200":
description: sh1pt projects returned description: Credential providers returned
/api/plugins/sh1pt/actions/publish: /api/credentials/plans:
post: post:
summary: Publish a sh1pt action into CommandBoard.run summary: Create a redacted credential sync plan
responses: responses:
"202": "201":
description: sh1pt action accepted description: Credential sync plan created
/api/schemas: /api/schemas:
get: get:
summary: List supported LogicSRC schema kinds summary: List supported LogicSRC schema kinds

View file

@ -11,10 +11,10 @@ The projects can be complementary. LogicSRC should support an `--openspec` compa
| Primary scope | Open coordination standards for humans, AI agents, plugins, payments, hosted products, and reference implementations. | Lightweight spec-driven planning framework for code changes and agent work. | | Primary scope | Open coordination standards for humans, AI agents, plugins, payments, hosted products, and reference implementations. | Lightweight spec-driven planning framework for code changes and agent work. |
| Main artifact shape | Versioned schemas, plugin manifests, event contracts, task/agent/run documents, SDK contracts, MCP resources, CLI/TUI/PWA/API surfaces. | Repo-local specs, proposals, design docs, tasks, and spec deltas. | | Main artifact shape | Versioned schemas, plugin manifests, event contracts, task/agent/run documents, SDK contracts, MCP resources, CLI/TUI/PWA/API surfaces. | Repo-local specs, proposals, design docs, tasks, and spec deltas. |
| Agent relationship | Agent profiles, runs, audit logs, model routing, AgentSwarm orchestration, and provider-neutral execution records. | Planning layer that gives coding agents persistent requirements and change context. | | Agent relationship | Agent profiles, runs, audit logs, model routing, AgentSwarm orchestration, and provider-neutral execution records. | Planning layer that gives coding agents persistent requirements and change context. |
| CLI direction | `logicsrc`, plus compatible product aliases and `sh1pt logicsrc ...`. | `@fission-ai/openspec` CLI and slash-command integrations with coding tools. | | CLI direction | `logicsrc` as the canonical OpenStandards CLI. | `@fission-ai/openspec` CLI and slash-command integrations with coding tools. |
| MCP | LogicSRC has a standards MCP server and should expose resources, tools, and prompts. | Site states "No MCP" as a product trait. | | MCP | LogicSRC has a standards MCP server and should expose resources, tools, and prompts. | Site states "No MCP" as a product trait. |
| SDK/API | Planned Rust, Bun, Node, Python, curl, and PWA surfaces with matching contracts. | Focus appears to be repo workflow and agent planning artifacts rather than a cross-language SDK/API standard. | | SDK/API | Planned Rust, Bun, Node, Python, curl, and PWA surfaces with matching contracts. | Focus appears to be repo workflow and agent planning artifacts rather than a cross-language SDK/API standard. |
| Plugins | Plugin manifest standard plus CoinPay, uGig, sh1pt, AgentByte, and future integration specs. | Integrates with many coding agents and editors; plugin-contract scope is not the main positioning. | | Plugins | Plugin manifest standard plus CoinPay, uGig, AgentByte, Credential Sharing, and future integration specs. | Integrates with many coding agents and editors; plugin-contract scope is not the main positioning. |
| Compatibility idea | `logicsrc --openspec` reads/writes OpenSpec.dev-style specs/proposals/tasks where useful. | Can remain the lightweight planning layer inside repos. | | Compatibility idea | `logicsrc --openspec` reads/writes OpenSpec.dev-style specs/proposals/tasks where useful. | Can remain the lightweight planning layer inside repos. |
## CLI Flags ## CLI Flags
@ -24,7 +24,6 @@ logicsrc --openspec agentswarm --yolo --repo profullstack/logicsrc
logicsrc openspec import logicsrc openspec import
logicsrc openspec export --out logicsrc-openspec-summary.md logicsrc openspec export --out logicsrc-openspec-summary.md
logicsrc --openspec-only task validate ./task.yaml logicsrc --openspec-only task validate ./task.yaml
sh1pt logicsrc --openspec agentswarm --yolo --repo profullstack/logicsrc
``` ```
- `--openspec` enables OpenSpec.dev-compatible repo-local planning conventions where supported. - `--openspec` enables OpenSpec.dev-compatible repo-local planning conventions where supported.

View file

@ -6,11 +6,12 @@ Default plugins:
- CoinPay: DID auth, wallet, payment, escrow, refunds, tips, payment webhooks, and payment reputation. - CoinPay: DID auth, wallet, payment, escrow, refunds, tips, payment webhooks, and payment reputation.
- uGig: job import, gig publishing, candidate/agent linking, bid sync, marketplace publishing, and reputation sync. - uGig: job import, gig publishing, candidate/agent linking, bid sync, marketplace publishing, and reputation sync.
- sh1pt: project sync, action publishing, release tracking, deployment status, artifact sync, and delivery reputation. - Credential Sharing: provider-neutral secret sync plans, approvals, rollbacks, and audit events.
Coming soon plugin specs: Coming soon plugin specs:
- AgentByte: candidate, contractor, and agent capability screening for AI-era workflows. See `docs/agent-screening.md`. - AgentByte: candidate, contractor, and agent capability screening for AI-era workflows. See `docs/agent-screening.md`.
- Credential Sharing: replacement architecture for .env, Doppler, Railway variables, GitHub Secrets, and future providers. See `docs/credential-sharing.md`.
Runtime requirements: Runtime requirements:
@ -25,21 +26,17 @@ Runtime requirements:
Manifest shape is defined by `packages/schemas/schemas/logicsrc-plugin.schema.json`. Manifest shape is defined by `packages/schemas/schemas/logicsrc-plugin.schema.json`.
## sh1pt ## Credential Sharing
The sh1pt plugin connects project delivery workflows to CommandBoard.run boards and LogicSRC tasks. Its default board is `/projects/sh1pt`.
Capabilities: Capabilities:
```txt ```txt
projects.sync credentials.providers
actions.import credentials.inspect
actions.publish credentials.diff
tasks.create_from_action credentials.plan
releases.sync credentials.approve
deployments.create credentials.sync
deployments.status credentials.rollback
artifacts.sync credentials.audit
webhook.delivery_status
reputation.delivery_event
``` ```

View file

@ -18,6 +18,6 @@ Avoid using "LogicSRC Foundation" unless Profullstack creates a separate legal f
LogicSRC defines the common language and primitives: identity, boards, posts, tasks, bounties, agents, agent runs, permissions, payments, escrow, reputation, events, webhooks, CLI commands, SDK contracts, MCP servers, PWA states, curl/API surfaces, and schemas. LogicSRC defines the common language and primitives: identity, boards, posts, tasks, bounties, agents, agent runs, permissions, payments, escrow, reputation, events, webhooks, CLI commands, SDK contracts, MCP servers, PWA states, curl/API surfaces, and schemas.
CommandBoard.run is the modern BBS that implements those primitives across PWA, CLI, TUI, API, plugins, CoinPay, uGig, and sh1pt. CommandBoard.run is one reference product that implements those primitives across PWA, CLI, TUI, API, plugins, CoinPay, and uGig.
sh1pt is a separate Profullstack product CLI that can host LogicSRC as `sh1pt logicsrc ...`. That path is for users who want sh1pt delivery automation while restricting a workflow to OpenSpec contracts from LogicSRC. External products can consume LogicSRC contracts, but LogicSRC remains the open standards layer and should not depend on product-specific command paths.

View file

@ -6,14 +6,14 @@
4. Add plugin-core package. 4. Add plugin-core package.
5. Add CoinPay plugin. 5. Add CoinPay plugin.
6. Add uGig plugin. 6. Add uGig plugin.
7. Add sh1pt plugin. 7. Add Credential Sharing OpenSpec.
8. Add CommandBoard.run API. 8. Add CommandBoard.run API.
9. Add auth and DID connection. 9. Add auth and DID connection.
10. Add boards and posts. 10. Add boards and posts.
11. Add task schema validation. 11. Add task schema validation.
12. Add CoinPay escrow integration. 12. Add CoinPay escrow integration.
13. Add uGig jobs/gigs integration. 13. Add uGig jobs/gigs integration.
14. Add sh1pt projects/actions integration. 14. Add credential provider adapters for .env, Doppler, Railway variables, and GitHub Secrets.
15. Add `logicsrc` CLI. 15. Add `logicsrc` CLI.
16. Add installer script. 16. Add installer script.
17. Add CLI update/upgrade. 17. Add CLI update/upgrade.
@ -26,6 +26,6 @@
24. Add plugin status UI. 24. Add plugin status UI.
25. Add SDK contracts for Rust, Bun, Node, Python, and curl. 25. Add SDK contracts for Rust, Bun, Node, Python, and curl.
26. Add MCP server contracts. 26. Add MCP server contracts.
27. Add `sh1pt logicsrc ...` OpenSpec-only integration. 27. Add credential sync audit exports.
28. Add docs. 28. Add docs.
29. Tag v1.0.0. 29. Tag v1.0.0.

4
package-lock.json generated
View file

@ -4655,15 +4655,12 @@
"dependencies": { "dependencies": {
"@logicsrc/plugin-coinpay": "file:../../plugins/coinpay", "@logicsrc/plugin-coinpay": "file:../../plugins/coinpay",
"@logicsrc/plugin-core": "file:../plugin-core", "@logicsrc/plugin-core": "file:../plugin-core",
"@logicsrc/plugin-sh1pt": "file:../../plugins/sh1pt",
"@logicsrc/plugin-ugig": "file:../../plugins/ugig", "@logicsrc/plugin-ugig": "file:../../plugins/ugig",
"@logicsrc/tui": "file:../tui", "@logicsrc/tui": "file:../tui",
"@logicsrc/validators": "file:../validators", "@logicsrc/validators": "file:../validators",
"commander": "^14.0.2" "commander": "^14.0.2"
}, },
"bin": { "bin": {
"cb": "dist/index.js",
"commandboard": "dist/index.js",
"logicsrc": "dist/index.js" "logicsrc": "dist/index.js"
}, },
"devDependencies": { "devDependencies": {
@ -4713,7 +4710,6 @@
"dependencies": { "dependencies": {
"@logicsrc/plugin-coinpay": "file:../../plugins/coinpay", "@logicsrc/plugin-coinpay": "file:../../plugins/coinpay",
"@logicsrc/plugin-core": "file:../plugin-core", "@logicsrc/plugin-core": "file:../plugin-core",
"@logicsrc/plugin-sh1pt": "file:../../plugins/sh1pt",
"@logicsrc/plugin-ugig": "file:../../plugins/ugig" "@logicsrc/plugin-ugig": "file:../../plugins/ugig"
} }
}, },

View file

@ -6,9 +6,7 @@
"main": "./dist/index.js", "main": "./dist/index.js",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
"bin": { "bin": {
"logicsrc": "./dist/index.js", "logicsrc": "./dist/index.js"
"commandboard": "./dist/index.js",
"cb": "./dist/index.js"
}, },
"scripts": { "scripts": {
"build": "tsc -p tsconfig.json", "build": "tsc -p tsconfig.json",
@ -18,7 +16,6 @@
"dependencies": { "dependencies": {
"@logicsrc/plugin-core": "file:../plugin-core", "@logicsrc/plugin-core": "file:../plugin-core",
"@logicsrc/plugin-coinpay": "file:../../plugins/coinpay", "@logicsrc/plugin-coinpay": "file:../../plugins/coinpay",
"@logicsrc/plugin-sh1pt": "file:../../plugins/sh1pt",
"@logicsrc/plugin-ugig": "file:../../plugins/ugig", "@logicsrc/plugin-ugig": "file:../../plugins/ugig",
"@logicsrc/tui": "file:../tui", "@logicsrc/tui": "file:../tui",
"@logicsrc/validators": "file:../validators", "@logicsrc/validators": "file:../validators",

View file

@ -2,11 +2,11 @@ import { describe, expect, it } from "vitest";
import { defaultPluginRegistry } from "./registry.js"; import { defaultPluginRegistry } from "./registry.js";
describe("CLI registry", () => { describe("CLI registry", () => {
it("loads default v1 plugins", () => { it("loads open standards plugins only", () => {
const ids = defaultPluginRegistry().snapshot().plugins.map((plugin: { id: string }) => plugin.id); const ids = defaultPluginRegistry().snapshot().plugins.map((plugin: { id: string }) => plugin.id);
expect(ids).toContain("coinpay"); expect(ids).toContain("coinpay");
expect(ids).toContain("ugig"); expect(ids).toContain("ugig");
expect(ids).toContain("sh1pt"); expect(ids).not.toContain("sh1pt");
}); });
}); });

View file

@ -1,6 +1,5 @@
#!/usr/bin/env node #!/usr/bin/env node
import { readFileSync } from "node:fs"; import { readFileSync } from "node:fs";
import { basename } from "node:path";
import { Command } from "commander"; import { Command } from "commander";
import { renderPluginStatus, renderTui } from "@logicsrc/tui"; import { renderPluginStatus, renderTui } from "@logicsrc/tui";
import { assertSchemaKind, parseDocument, validate } from "@logicsrc/validators"; import { assertSchemaKind, parseDocument, validate } from "@logicsrc/validators";
@ -10,12 +9,9 @@ import { exportOpenSpecSummary, importOpenSpec, writeOpenSpecChange } from "./op
import { defaultPluginRegistry } from "./registry.js"; import { defaultPluginRegistry } from "./registry.js";
const program = new Command(); const program = new Command();
const binaryName = basename(process.argv[1] ?? "");
const commandName = binaryName === "commandboard" || binaryName === "cb" ? binaryName : "logicsrc";
program program
.name(commandName) .name("logicsrc")
.aliases(["commandboard", "cb"])
.description("LogicSRC OpenSpec CLI for schemas, boards, tasks, agents, payments, plugins, and TUI.") .description("LogicSRC OpenSpec CLI for schemas, boards, tasks, agents, payments, plugins, and TUI.")
.option("--openspec", "Enable OpenSpec.dev-compatible repo-local specs, proposals, tasks, and deltas where supported.") .option("--openspec", "Enable OpenSpec.dev-compatible repo-local specs, proposals, tasks, and deltas where supported.")
.option("--openspec-only", "Restrict workflows to LogicSRC OpenSpec schemas, SDKs, MCP, CLI, TUI, and PWA contracts.") .option("--openspec-only", "Restrict workflows to LogicSRC OpenSpec schemas, SDKs, MCP, CLI, TUI, and PWA contracts.")
@ -29,11 +25,11 @@ program
.action((options) => { .action((options) => {
const mode = options.did ? `CoinPay DID ${options.did}` : options.oauth ? `${options.oauth} OAuth` : "browser/device"; const mode = options.did ? `CoinPay DID ${options.did}` : options.oauth ? `${options.oauth} OAuth` : "browser/device";
console.log(`Login flow ready: ${mode}`); console.log(`Login flow ready: ${mode}`);
console.log("Token storage target: $HOME/.commandboard/auth.json"); console.log("Token storage target: $HOME/.logicsrc/auth.json");
}); });
program.command("logout").description("Clear local auth token.").action(() => { program.command("logout").description("Clear local auth token.").action(() => {
console.log("Logged out. Local auth token would be removed from $HOME/.commandboard/auth.json."); console.log("Logged out. Local auth token would be removed from $HOME/.logicsrc/auth.json.");
}); });
program.command("whoami").description("Show current DID and account context.").action(() => { program.command("whoami").description("Show current DID and account context.").action(() => {
@ -216,38 +212,32 @@ program.command("plugins").option("--format <format>", "table, json, or markdown
print(snapshot.plugins, options.format as OutputFormat); print(snapshot.plugins, options.format as OutputFormat);
}); });
const sh1pt = program.command("sh1pt").description("sh1pt project, action, release, and delivery commands."); const credentials = program.command("credentials").alias("creds").description("Credential-sharing OpenSpec commands.");
sh1pt credentials.command("providers").option("--format <format>", "table, json, or markdown", "table").description("List credential sharing provider targets.").action((options) => {
.command("projects") print(
.option("--format <format>", "table, json, or markdown", "table") [
.description("List synced sh1pt projects.") { id: "env", target: ".env files", mode: "read/write" },
.action((options) => { { id: "doppler", target: "Doppler projects/configs", mode: "sync" },
print( { id: "railway", target: "Railway service variables", mode: "sync" },
[ { id: "github-secrets", target: "GitHub Actions and environment secrets", mode: "sync" }
{ id: "sh1pt_project_1", board: "/projects/sh1pt", status: "active", actions: 5 }, ],
{ id: "sh1pt_project_2", board: "/projects/crawlproof", status: "active", actions: 2 } options.format as OutputFormat
], );
options.format as OutputFormat });
);
});
sh1pt credentials.command("plan").option("--from <provider>", "Source provider", "env").option("--to <provider>", "Destination provider", "railway").option("--format <format>", "table, json, or markdown", "table").description("Describe a credential sync plan without moving secrets.").action((options) => {
.command("actions") print(
.option("--format <format>", "table, json, or markdown", "table") {
.description("List sh1pt actions available for task publishing.") type: "logicsrc.credential_sync_plan",
.action((options) => { from: options.from,
print( to: options.to,
[ policy: "redact-values",
{ id: "action_release_checklist", title: "Release checklist", publishable: true }, approval: "required-before-write",
{ id: "action_deploy_preview", title: "Deploy preview", publishable: true } audit: "write target, key names, fingerprints, and timestamps; never write raw secret values"
], },
options.format as OutputFormat options.format as OutputFormat
); );
});
sh1pt.command("publish").argument("<action>", "sh1pt action id").option("--board <board>", "Target board", "/projects/sh1pt").description("Publish a sh1pt action as a CommandBoard task.").action((action, options) => {
console.log(`Published sh1pt action ${action} to ${options.board}`);
}); });
program.command("tui").description("Launch the tmux-friendly TUI.").action(() => { program.command("tui").description("Launch the tmux-friendly TUI.").action(() => {
@ -255,16 +245,16 @@ program.command("tui").description("Launch the tmux-friendly TUI.").action(() =>
console.log("\nPlugin status:\n" + renderPluginStatus()); console.log("\nPlugin status:\n" + renderPluginStatus());
}); });
program.command("update").alias("upgrade").description("Update the local CommandBoard.run CLI.").action(() => { program.command("update").alias("upgrade").description("Update the local LogicSRC CLI.").action(() => {
console.log("Current version: 0.1.0"); console.log("Current version: 0.1.0");
console.log("Latest version: 0.1.0"); console.log("Latest version: 0.1.0");
console.log("CommandBoard.run CLI is already up to date."); console.log("LogicSRC CLI is already up to date.");
console.log("Config preserved at $HOME/.commandboard"); console.log("Config preserved at $HOME/.logicsrc");
}); });
program.command("remove").alias("uninstall").option("--purge", "Remove config and auth tokens").description("Remove local CommandBoard.run CLI.").action((options) => { program.command("remove").alias("uninstall").option("--purge", "Remove config and auth tokens").description("Remove local LogicSRC CLI.").action((options) => {
console.log("Removed CommandBoard.run CLI."); console.log("Removed LogicSRC CLI.");
console.log(options.purge ? "Removed config and auth tokens from $HOME/.commandboard." : "Preserved config at $HOME/.commandboard. Run with --purge to remove config and auth tokens."); console.log(options.purge ? "Removed config and auth tokens from $HOME/.logicsrc." : "Preserved config at $HOME/.logicsrc. Run with --purge to remove config and auth tokens.");
}); });
function validateFile(kindArg: string, file: string) { function validateFile(kindArg: string, file: string) {

View file

@ -1,8 +1,7 @@
import { createPluginRegistry } from "@logicsrc/plugin-core"; import { createPluginRegistry } from "@logicsrc/plugin-core";
import { coinPayPlugin } from "@logicsrc/plugin-coinpay"; import { coinPayPlugin } from "@logicsrc/plugin-coinpay";
import { sh1ptPlugin } from "@logicsrc/plugin-sh1pt";
import { uGigPlugin } from "@logicsrc/plugin-ugig"; import { uGigPlugin } from "@logicsrc/plugin-ugig";
export function defaultPluginRegistry() { export function defaultPluginRegistry() {
return createPluginRegistry([coinPayPlugin, uGigPlugin, sh1ptPlugin]); return createPluginRegistry([coinPayPlugin, uGigPlugin]);
} }

View file

@ -1,7 +1,7 @@
{ {
"name": "@logicsrc/tui", "name": "@logicsrc/tui",
"version": "0.1.0", "version": "0.1.0",
"description": "CommandBoard.run terminal UI.", "description": "LogicSRC terminal UI.",
"type": "module", "type": "module",
"main": "./dist/index.js", "main": "./dist/index.js",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
@ -11,7 +11,6 @@
"dependencies": { "dependencies": {
"@logicsrc/plugin-core": "file:../plugin-core", "@logicsrc/plugin-core": "file:../plugin-core",
"@logicsrc/plugin-coinpay": "file:../../plugins/coinpay", "@logicsrc/plugin-coinpay": "file:../../plugins/coinpay",
"@logicsrc/plugin-sh1pt": "file:../../plugins/sh1pt",
"@logicsrc/plugin-ugig": "file:../../plugins/ugig" "@logicsrc/plugin-ugig": "file:../../plugins/ugig"
} }
} }

View file

@ -1,6 +1,5 @@
import { createPluginRegistry } from "@logicsrc/plugin-core"; import { createPluginRegistry } from "@logicsrc/plugin-core";
import { coinPayPlugin } from "@logicsrc/plugin-coinpay"; import { coinPayPlugin } from "@logicsrc/plugin-coinpay";
import { sh1ptPlugin } from "@logicsrc/plugin-sh1pt";
import { uGigPlugin } from "@logicsrc/plugin-ugig"; import { uGigPlugin } from "@logicsrc/plugin-ugig";
export interface TuiState { export interface TuiState {
@ -19,11 +18,11 @@ const defaultState: TuiState = {
export function renderTui(state: Partial<TuiState> = {}) { export function renderTui(state: Partial<TuiState> = {}) {
const view = { ...defaultState, ...state }; const view = { ...defaultState, ...state };
const registry = createPluginRegistry([coinPayPlugin, uGigPlugin, sh1ptPlugin]); const registry = createPluginRegistry([coinPayPlugin, uGigPlugin]);
const plugins = registry.snapshot().plugins; const plugins = registry.snapshot().plugins;
return [ return [
"┌─ CommandBoard.run ──────────────────────────────────────────┐", "┌─ LogicSRC TUI ──────────────────────────────────────────────┐",
`│ DID: ${pad(view.did, 17)} Board: ${pad(view.board, 7)} Rep: ${String(view.reputation).padEnd(3)} Balance: ${pad(view.balance, 6)}`, `│ DID: ${pad(view.did, 17)} Board: ${pad(view.board, 7)} Rep: ${String(view.reputation).padEnd(3)} Balance: ${pad(view.balance, 6)}`,
"├───────────────┬─────────────────────────────────────────────┤", "├───────────────┬─────────────────────────────────────────────┤",
"│ Boards │ Feed │", "│ Boards │ Feed │",
@ -31,7 +30,6 @@ export function renderTui(state: Partial<TuiState> = {}) {
"│ /agents │ [POST] New agent plugin idea │", "│ /agents │ [POST] New agent plugin idea │",
"│ /qa │ [RUN] qa-agent completed task_123 │", "│ /qa │ [RUN] qa-agent completed task_123 │",
"│ /jobs │ [uGig] Senior AI Engineer remote │", "│ /jobs │ [uGig] Senior AI Engineer remote │",
"│ /projects │ [sh1pt] Release action published │",
"├───────────────┴─────────────────────────────────────────────┤", "├───────────────┴─────────────────────────────────────────────┤",
"│ Plugins: " + plugins.map((plugin) => `${plugin.name} ${plugin.enabled ? "enabled" : "disabled"}`).join(" | ").padEnd(50) + " │", "│ Plugins: " + plugins.map((plugin) => `${plugin.name} ${plugin.enabled ? "enabled" : "disabled"}`).join(" | ").padEnd(50) + " │",
"│ Enter: open p: post t: task a: agents w: wallet q: quit │", "│ Enter: open p: post t: task a: agents w: wallet q: quit │",
@ -40,7 +38,7 @@ export function renderTui(state: Partial<TuiState> = {}) {
} }
export function renderPluginStatus() { export function renderPluginStatus() {
const registry = createPluginRegistry([coinPayPlugin, uGigPlugin, sh1ptPlugin]); const registry = createPluginRegistry([coinPayPlugin, uGigPlugin]);
return registry return registry
.snapshot() .snapshot()
.plugins.map((plugin) => `${plugin.id.padEnd(8)} ${plugin.enabled ? "enabled" : "disabled"} ${plugin.type.join(", ")}`) .plugins.map((plugin) => `${plugin.id.padEnd(8)} ${plugin.enabled ? "enabled" : "disabled"} ${plugin.type.join(", ")}`)