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.
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()).
- Adhere to
AGENTS.mdandCLAUDE.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.
- Initialized
CONTINUITY.mdto track session state. - Updated
AGENTS.mdwith 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
apiPublishingwill 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}/runson same-origin (studio.giselles.ai), with conventions: no trailing slash, JSON, reserveAuthorizationheader for API key auth (exact scheme TBD). - TEMPORARY agreement (spec-only; delete once implemented): persist API publishing settings in the protocol
Appobject for portability (Studio + self-hosted). Store only non-secret config inApp:apiPublishing.isEnabled: booleanapiPublishing.apiKeyId?: ApiKeyId(reference only; never store the secret in App JSON)- Do not persist endpoint string; derive it from
appIdand 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.
- Token format:
- 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
ApiSecretRecordperapiKeyIdatapiSecretPath(apiKeyId); no scans). - Active-key policy is best-effort single-active:
createApiSecretrevokes the previous key if present; verification accepts any non-revoked record for the requestedappId(does not enforce “currentapp.apiPublishing.apiKeyIdonly”).
- Repository is a large monorepo (>10k commits) using pnpm and turbo.
- Architecture involves
apps(playground, studio) andpackages(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.
-
Explored workspace structure.
-
Analyzed
package.json,pnpm-workspace.yaml. -
Inspected
apps/andpackages/contents. -
Verified naming conventions and code style.
-
Checked error handling patterns.
-
Updated
AGENTS.mdwith gathered information. -
Added "Development Philosophy" section from
CLAUDE.mdtoAGENTS.md. -
Added "Update CONTINUITY.md" to "After Every Code Change" section in
AGENTS.md. -
Added
CONTINUITY.mdoperation guidance inAGENTS.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
apiPublishingfeature flag:- Added
apiPublishingFlagtoapps/studio.giselles.ai/flags.ts. - Added
apiPublishingtoFeatureFlagContextValueinpackages/react/src/feature-flags/context.ts. - Added to
WorkspaceProviderinpackages/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.tsxto conditionally render API publishing section.
- Added
-
Started implementing API publishing key management schemas in
packages/protocol(api-publishing/api-secret.ts). -
Added protocol exports for API publishing and extended
Appschema withapiPublishing(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.revokeApiSecretmethods). -
(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-sdkfailure: replaced promisifiedcrypto.scryptcall with a typed async wrapper for TS DTS generation. -
Added a short comment explaining the
gsk_token prefix meaning inpackages/giselle/src/api-publishing/token.ts. -
Added
createApiSecretandrevokeApiSecretJSON routes to@giselles-ai/http(packages/http/src/router.ts) to matchpackages/giselle/src/giselle.ts. -
Updated
AGENTS.mdwith a rule: when adding a new public API topackages/giselle/src/giselle.ts, also add the corresponding route inpackages/http/src/router.ts. -
Refactored API publishing UI to use
useGiselle()client methods instead of manualfetch()calls, and added agetCurrentApiSecretRecordForAppAPI/route to support that. -
Fixed build/type errors: removed duplicate export of
getCurrentApiSecretRecordForAppinpackages/giselle/src/api-publishing/api-secrets.tsand updated studio route to callgiselle.getCurrentApiSecretRecordForApp. -
Simplified App Entry properties panel to secret key creation only (removed run/revoke/toggle flows for now).
-
Hardened
lastUsedAtupdates to reduce the chance of overwriting a concurrent revoke. -
Updated Studio docs to describe
scryptenv vars for API secret hashing (and removedGISELLE_API_SECRET_PEPPER). -
Started removing
hmac-sha256support for API secret hashing (protocol schema updated toscrypt-only). -
Simplified protocol
ApiSecretKdfschema to the singlescryptvariant. -
Added
GiselleConfig.apiSecretScryptto allow configuring scrypt params + salt size + optional duration logging. -
Updated
GiselleContextto carryapiSecretScrypt(replacing the removed pepper field). -
Refactored API publishing secret hashing to be
scrypt-only, with optional duration logging for observability. -
Updated
packages/giselleAPI secret tests to match thescrypt-only implementation. -
Updated Studio Giselle initialization to configure
apiSecretScryptvia env (and removed pepper usage). -
Updated Playground Giselle initialization to configure
apiSecretScryptvia env (and removed pepper usage). -
Added a new
GenerationOrigintype:api(public API executions). -
Added a Studio API Route to run an App via API key:
POST /api/apps/{appId}/runwith body{ text: string }andAuthorization: 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/giselleexports 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
appIdeasily.
-
Requested: run
mise doctorin 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).
createApiSecretattempts best-effort single-active by revoking the previous key if present, but verification is record-based and does not enforce “currentapp.apiPublishing.apiKeyIdonly”. -
Security follow-up: Code scanning flagged
hmac-sha256for API secret hashing; plan is to remove HMAC and standardize onscryptwith 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-aito@giselles-ai/sdk. -
Added SDK tests for
packages/sdk(mocked fetch; validates auth/header/path, rejectsinput.file,runAndWaitstub). -
packages/sdkformat (Biome) + tests (Vitest) are passing. -
Added
packages/sdk/README.mddocumenting usage, auth, and current limitations. -
Updated
@giselles-ai/sdkto defaultbaseUrltohttps://studio.giselles.ai(no browser use case assumed). -
Updated
@giselles-ai/sdktests to cover the defaultbaseUrlbehavior. -
Updated
packages/sdk/README.mdto reflect the newbaseUrldefault and remove browser guidance. -
Refined
packages/sdk/README.mdusage example to omitbaseUrlon the happy path and added a server-side-only note. -
Updated
packages/sdk/README.mdusage example to avoid top-levelawait(works withtsx index.ts).
- Add documentation / examples for the public run API (
curlusage) 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.
- 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 → keyIdsindex (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
scryptparameters 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 (viaGiselleConfig/ env) so we can adjust them later without a refactor.
- Key lifecycle
- Create: generate
apiKeyId+ randomsecret→ storesecretHashwithapiKeyId/appId(+ timestamps) → return token once → updateapp.apiPublishing.apiKeyIdif this key is the primary one. - Rotate: create new key → update
app.apiPublishing.apiKeyIdto new → revoke previous key (setrevokedAt) depending on chosen active-key policy. - Revoke: set
revokedAt; if revoked key is the currentapp.apiPublishing.apiKeyId, clear or replace it.
- Create: generate
- Request verification
- Parse
Authorization: Bearer gsk_{apiKeyId}.{secret}. - Load ApiKey by
apiKeyId(no search-by-prefix). - Verify not revoked and
appIdmatches the requested app. - Compute hash(secret) and constant-time compare with stored
secretHash.
- Parse
internal-packages/workflow-designer-ui/src/editor/properties-panel/app-entry-node-properties-panel/app-entry-configured-view.tsxapps/studio.giselles.ai/flags.tspackages/react/src/feature-flags/context.tspackages/react/src/workspace/provider.tsxapps/studio.giselles.ai/app/workspaces/[workspaceId]/data-loader.tsAGENTS.mdCONTINUITY.mdpackages/sdk/*