Skip to content

Latest commit

 

History

History
147 lines (130 loc) · 12.5 KB

File metadata and controls

147 lines (130 loc) · 12.5 KB

Continuity Ledger (batched snapshot)

This file is a low-churn, batched snapshot (“as of ”) of the repo’s current focus and key decisions.

Recent, detailed intent logs live in .continuity/ (per-branch ledgers). Periodically summarize .continuity/* into this file.

Goal

Add a public Runs SDK package (@giselles-ai/sdk) under packages/ to call POST /api/apps/{appId}/run and expose client.apps.run() (and a stubbed runAndWait()).

Constraints/Assumptions

  • Adhere to AGENTS.md and CLAUDE.md.
  • Use English for all code and documentation unless strictly required otherwise.
  • Maintain the "Less is more" philosophy.
  • Data structure for API settings will be designed separately (UI-only implementation for now).
  • Feature must be behind feature flag for safe production deploy.

Key decisions

  • Initialized CONTINUITY.md to track session state.
  • Updated AGENTS.md with architectural insights from codebase exploration.
  • Added API publishing toggle and display section in app-entry-configured-view.tsx.
  • Used temporary state for API enabled flag (data structure to be determined separately).
  • Feature flag apiPublishing will protect the new UI.
  • Documented Feature Flags usage pattern in AGENTS.md.
  • TEMPORARY agreement (spec-only; delete once implemented): public API endpoint format will be POST /api/v1/apps/{appId}/runs on same-origin (studio.giselles.ai), with conventions: no trailing slash, JSON, reserve Authorization header for API key auth (exact scheme TBD).
  • TEMPORARY agreement (spec-only; delete once implemented): persist API publishing settings in the protocol App object for portability (Studio + self-hosted). Store only non-secret config in App:
    • apiPublishing.isEnabled: boolean
    • apiPublishing.apiKeyId?: ApiKeyId (reference only; never store the secret in App JSON)
    • Do not persist endpoint string; derive it from appId and the agreed URL (POST /api/v1/apps/{appId}/runs).
  • TEMPORARY agreement (spec-only; delete once implemented): API key design for API publishing:
    • Token format: gsk_{apiKeyId}.{secret}
    • Auth header: Authorization: Bearer <token>
    • Secret storage: hash-only (do NOT store plaintext; do NOT store decryptable ciphertext). The secret is shown once at creation and is not retrievable later.
    • App stores only references/flags (no secret): app.apiPublishing.apiKeyId?: ApiKeyId
    • UI must change accordingly: remove “copy API key” for existing keys; instead use “Create new key” → show-once modal and then only show fingerprint/metadata + revoke/rotate actions.
  • TEMPORARY agreement (spec-only; delete once implemented): public Runs API design is deferred for now; we keep only secret key generation in the App Entry properties panel.
  • Api secret key records live in Giselle Storage (one ApiSecretRecord per apiKeyId at apiSecretPath(apiKeyId); no scans).
  • Active-key policy is best-effort single-active: createApiSecret revokes the previous key if present; verification accepts any non-revoked record for the requested appId (does not enforce “current app.apiPublishing.apiKeyId only”).

State

  • Repository is a large monorepo (>10k commits) using pnpm and turbo.
  • Architecture involves apps (playground, studio) and packages (giselle, protocol, etc.).
  • API publishing UI implemented with toggle, endpoint display, and API key display with copy functionality.
  • Feature Flags documentation added to AGENTS.md.

Done

  • Explored workspace structure.

  • Analyzed package.json, pnpm-workspace.yaml.

  • Inspected apps/ and packages/ contents.

  • Verified naming conventions and code style.

  • Checked error handling patterns.

  • Updated AGENTS.md with gathered information.

  • Added "Development Philosophy" section from CLAUDE.md to AGENTS.md.

  • Added "Update CONTINUITY.md" to "After Every Code Change" section in AGENTS.md.

  • Added CONTINUITY.md operation guidance in AGENTS.md: track unresolved design decisions under Open questions and reserve Next for concrete execution steps.

  • Added API publishing toggle to App Entry Node Properties Panel.

  • Added API endpoint and authentication key display with copy functionality.

  • Documented Feature Flags usage in AGENTS.md.

  • Implemented apiPublishing feature flag:

    • Added apiPublishingFlag to apps/studio.giselles.ai/flags.ts.
    • Added apiPublishing to FeatureFlagContextValue in packages/react/src/feature-flags/context.ts.
    • Added to WorkspaceProvider in packages/react/src/workspace/provider.tsx.
    • Added to data-loader in apps/studio.giselles.ai/app/workspaces/[workspaceId]/data-loader.ts.
    • Used flag in app-entry-configured-view.tsx to conditionally render API publishing section.
  • Started implementing API publishing key management schemas in packages/protocol (api-publishing/api-secret.ts).

  • Added protocol exports for API publishing and extended App schema with apiPublishing (non-secret settings).

  • Added Giselle Storage path helper for API secrets and started implementing API secret key management in packages/giselle (token parsing + create/revoke/verify).

  • Exposed API secret key management APIs from @giselles-ai/giselle (exports + giselle.createApiSecret / giselle.revokeApiSecret methods).

  • (Rolled back) Removed Studio API routes for API publishing under /api/v1/apps/{appId}/... for now; key generation is handled via the Giselle HTTP layer.

  • Updated App Entry Properties Panel API publishing UI to use show-once key creation and revoke (no copy of existing keys), behind apiPublishing.

  • Added unit tests for API publishing token parsing, hashing verification, and single-active revoke behavior in packages/giselle.

  • Fixed pnpm build-sdk failure: replaced promisified crypto.scrypt call with a typed async wrapper for TS DTS generation.

  • Added a short comment explaining the gsk_ token prefix meaning in packages/giselle/src/api-publishing/token.ts.

  • Added createApiSecret and revokeApiSecret JSON routes to @giselles-ai/http (packages/http/src/router.ts) to match packages/giselle/src/giselle.ts.

  • Updated AGENTS.md with a rule: when adding a new public API to packages/giselle/src/giselle.ts, also add the corresponding route in packages/http/src/router.ts.

  • Refactored API publishing UI to use useGiselle() client methods instead of manual fetch() calls, and added a getCurrentApiSecretRecordForApp API/route to support that.

  • Fixed build/type errors: removed duplicate export of getCurrentApiSecretRecordForApp in packages/giselle/src/api-publishing/api-secrets.ts and updated studio route to call giselle.getCurrentApiSecretRecordForApp.

  • Simplified App Entry properties panel to secret key creation only (removed run/revoke/toggle flows for now).

  • Hardened lastUsedAt updates to reduce the chance of overwriting a concurrent revoke.

  • Updated Studio docs to describe scrypt env vars for API secret hashing (and removed GISELLE_API_SECRET_PEPPER).

  • Started removing hmac-sha256 support for API secret hashing (protocol schema updated to scrypt-only).

  • Simplified protocol ApiSecretKdf schema to the single scrypt variant.

  • Added GiselleConfig.apiSecretScrypt to allow configuring scrypt params + salt size + optional duration logging.

  • Updated GiselleContext to carry apiSecretScrypt (replacing the removed pepper field).

  • Refactored API publishing secret hashing to be scrypt-only, with optional duration logging for observability.

  • Updated packages/giselle API secret tests to match the scrypt-only implementation.

  • Updated Studio Giselle initialization to configure apiSecretScrypt via env (and removed pepper usage).

  • Updated Playground Giselle initialization to configure apiSecretScrypt via env (and removed pepper usage).

  • Added a new GenerationOrigin type: api (public API executions).

  • Added a Studio API Route to run an App via API key: POST /api/apps/{appId}/run with body { text: string } and Authorization: Bearer gsk_{apiKeyId}.{secret}.

  • Updated origin-type switches/callbacks to handle api (task creation, generation execution, trigger resolution, file paths, Studio tracing + Trigger.dev processes).

  • Updated @giselles-ai/giselle exports to expose API publishing helpers needed by the Studio route.

  • Updated App Entry properties panel to show the API URL (copyable) above the Secret Key section so users can discover appId easily.

Now

  • Requested: run mise doctor in this worktree and report the output.

  • Spec work progressed: endpoint format, App persistence approach, and API key design (hash-only + show-once) are recorded as TEMPORARY agreements in this ledger.

  • Current behavior: key records live in Giselle Storage (hash-only). createApiSecret attempts best-effort single-active by revoking the previous key if present, but verification is record-based and does not enforce “current app.apiPublishing.apiKeyId only”.

  • Security follow-up: Code scanning flagged hmac-sha256 for API secret hashing; plan is to remove HMAC and standardize on scrypt with configurable parameters.

  • Public App Run API is implemented and callable locally; the next missing piece for richer inputs is a public File Upload API so Runs can accept files (e.g. { text, file: FileId }).

  • Started implementing SDK package packages/sdk (scaffold + initial client code).

  • Renamed the SDK npm package from giselle-ai to @giselles-ai/sdk.

  • Added SDK tests for packages/sdk (mocked fetch; validates auth/header/path, rejects input.file, runAndWait stub).

  • packages/sdk format (Biome) + tests (Vitest) are passing.

  • Added packages/sdk/README.md documenting usage, auth, and current limitations.

  • Updated @giselles-ai/sdk to default baseUrl to https://studio.giselles.ai (no browser use case assumed).

  • Updated @giselles-ai/sdk tests to cover the default baseUrl behavior.

  • Updated packages/sdk/README.md to reflect the new baseUrl default and remove browser guidance.

  • Refined packages/sdk/README.md usage example to omit baseUrl on the happy path and added a server-side-only note.

  • Updated packages/sdk/README.md usage example to avoid top-level await (works with tsx index.ts).

Next

  • Add documentation / examples for the public run API (curl usage) in an appropriate Studio doc page.
  • Add a public API to fetch task status/results for API-triggered runs (e.g. GET /api/tasks/{taskId} or a dedicated Runs API that returns outputs/steps).
  • Define and implement a public upload API to support file parameters in public runs.

Open questions (UNCONFIRMED if needed)

  • What minimal metadata/fingerprint do we need for Api secret records (e.g., createdAt, revokedAt, lastUsedAt, label, fingerprint)?
  • If we ever need key listing/rotation UX beyond “current key only”, do we need an appId → keyIds index (and where should it live)?
  • Should multi-active keys per App ever be supported (explicitly), or is best-effort single-active sufficient?
  • (Optional follow-up) When we revive the public Runs API, what should the request/response schema be?
  • What are the best scrypt parameters for API secret hashing in production (Vercel Functions)? Embed timing instrumentation in the hashing path, observe real numbers in the runtime environment, and decide parameters based on measurements. Ensure parameters are configurable (via GiselleConfig / env) so we can adjust them later without a refactor.

Implementation notes (spec-only; delete once implemented)

  • Key lifecycle
    • Create: generate apiKeyId + random secret → store secretHash with apiKeyId/appId (+ timestamps) → return token once → update app.apiPublishing.apiKeyId if this key is the primary one.
    • Rotate: create new key → update app.apiPublishing.apiKeyId to new → revoke previous key (set revokedAt) depending on chosen active-key policy.
    • Revoke: set revokedAt; if revoked key is the current app.apiPublishing.apiKeyId, clear or replace it.
  • Request verification
    • Parse Authorization: Bearer gsk_{apiKeyId}.{secret}.
    • Load ApiKey by apiKeyId (no search-by-prefix).
    • Verify not revoked and appId matches the requested app.
    • Compute hash(secret) and constant-time compare with stored secretHash.

Working set (files/ids/commands)

  • internal-packages/workflow-designer-ui/src/editor/properties-panel/app-entry-node-properties-panel/app-entry-configured-view.tsx
  • apps/studio.giselles.ai/flags.ts
  • packages/react/src/feature-flags/context.ts
  • packages/react/src/workspace/provider.tsx
  • apps/studio.giselles.ai/app/workspaces/[workspaceId]/data-loader.ts
  • AGENTS.md
  • CONTINUITY.md
  • packages/sdk/*