mirror of
https://github.com/Dvorinka/Primora.git
synced 2026-10-28 07:41:23 +00:00
feat: encrypted secrets vault across CLI, desktop, dashboard, and backend
Local vault (apps/cli): clean-room PRMVLT01 format — Argon2id → XChaCha20-Poly1305, AEAD-bound header, atomic writes. vault:* / secrets:* / inject (primora:// refs) / agent credential broker (dummy tokens in the child, real secret on the wire) / TTL sessions / stack:* operator group. Project vault (backend): core.project_secrets, AES-256-GCM via the platform encryptor. Metadata-only list, audit-logged reveal, and secret://NAME refs resolved at job delivery — refs stored, values never. Surfaces: dashboard Vault page (+ local-vault card under the Tauri shell), desktop vault window via IPC to the primora binary, secrets:* --remote CLI mode, metadata/write-only MCP tools so agents consume secrets via secret:// refs without holding plaintext. Authored By: TDvorak <[email protected]> Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
31bc23386b
commit
585bb04ab2
52 files changed
+3929
-142
No files matched your search
@@ -1838,6 +1838,91 @@ paths:
|
||||
description: text/event-stream of {type, occurred_at, data} messages
|
||||
"401":
|
||||
$ref: "#/components/responses/ErrorResponse"
|
||||
/projects/{projectID}/secrets:
|
||||
get:
|
||||
tags: [Secrets]
|
||||
operationId: listProjectSecrets
|
||||
summary: Lists project secrets — metadata only, values are never included.
|
||||
security:
|
||||
- bearerAuth: []
|
||||
- apiKeyAuth: []
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/ProjectID"
|
||||
responses:
|
||||
"200":
|
||||
description: Project secrets (metadata only)
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/ProjectSecretListResponse"
|
||||
"401":
|
||||
$ref: "#/components/responses/ErrorResponse"
|
||||
/projects/{projectID}/secrets/{name}:
|
||||
put:
|
||||
tags: [Secrets]
|
||||
operationId: setProjectSecret
|
||||
summary: Creates or replaces a project secret (AES-256-GCM at rest). Omitted url/notes keep existing values. Job payloads can reference it as secret://NAME, resolved at delivery.
|
||||
security:
|
||||
- bearerAuth: []
|
||||
- apiKeyAuth: []
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/ProjectID"
|
||||
- $ref: "#/components/parameters/SecretName"
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/SetProjectSecretRequest"
|
||||
responses:
|
||||
"200":
|
||||
description: Secret stored
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/ProjectSecret"
|
||||
"400":
|
||||
$ref: "#/components/responses/ErrorResponse"
|
||||
"401":
|
||||
$ref: "#/components/responses/ErrorResponse"
|
||||
delete:
|
||||
tags: [Secrets]
|
||||
operationId: deleteProjectSecret
|
||||
security:
|
||||
- bearerAuth: []
|
||||
- apiKeyAuth: []
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/ProjectID"
|
||||
- $ref: "#/components/parameters/SecretName"
|
||||
responses:
|
||||
"204":
|
||||
description: Secret deleted
|
||||
"401":
|
||||
$ref: "#/components/responses/ErrorResponse"
|
||||
"404":
|
||||
$ref: "#/components/responses/ErrorResponse"
|
||||
/projects/{projectID}/secrets/{name}/reveal:
|
||||
post:
|
||||
tags: [Secrets]
|
||||
operationId: revealProjectSecret
|
||||
summary: Returns the decrypted value. Every call is audit-logged.
|
||||
security:
|
||||
- bearerAuth: []
|
||||
- apiKeyAuth: []
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/ProjectID"
|
||||
- $ref: "#/components/parameters/SecretName"
|
||||
responses:
|
||||
"200":
|
||||
description: Decrypted value
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/RevealProjectSecretResponse"
|
||||
"401":
|
||||
$ref: "#/components/responses/ErrorResponse"
|
||||
"404":
|
||||
$ref: "#/components/responses/ErrorResponse"
|
||||
components:
|
||||
securitySchemes:
|
||||
bearerAuth:
|
||||
@@ -1863,6 +1948,13 @@ components:
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
SecretName:
|
||||
name: name
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
pattern: "^[A-Za-z_][A-Za-z0-9_]*$"
|
||||
BucketID:
|
||||
name: bucketID
|
||||
in: path
|
||||
@@ -3664,3 +3756,50 @@ components:
|
||||
items:
|
||||
$ref: "#/components/schemas/ScheduledJobRun"
|
||||
required: [items]
|
||||
ProjectSecret:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
format: uuid
|
||||
name:
|
||||
type: string
|
||||
description: Env-var-safe name; referenced as secret://NAME in job payloads.
|
||||
url:
|
||||
type: string
|
||||
notes:
|
||||
type: string
|
||||
created_at:
|
||||
type: string
|
||||
format: date-time
|
||||
updated_at:
|
||||
type: string
|
||||
format: date-time
|
||||
required: [id, name, url, notes, created_at, updated_at]
|
||||
ProjectSecretListResponse:
|
||||
type: object
|
||||
properties:
|
||||
items:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/ProjectSecret"
|
||||
required: [items]
|
||||
SetProjectSecretRequest:
|
||||
type: object
|
||||
properties:
|
||||
value:
|
||||
type: string
|
||||
description: Plaintext — stored AES-256-GCM encrypted, never returned by list.
|
||||
url:
|
||||
type: string
|
||||
notes:
|
||||
type: string
|
||||
required: [value]
|
||||
RevealProjectSecretResponse:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
value:
|
||||
type: string
|
||||
required: [name, value]
|
||||
Reference in new issue
Block a user