Repository navigation
security
MyPrompt runs as an Electron desktop app plus a standalone library. Three trust boundaries matter: the renderer/main process split, provider API keys at rest, and the split between public and privileged service clients.
desktop/main.ts creates the BrowserWindow with contextIsolation: true and nodeIntegration: false, so renderer code has no Node access. The only bridge is desktop/preload.ts, which exposes a fixed window.sentraDesktop surface through contextBridge: shell state, auth, workspace, a generic invoke, stream subscribe/unsubscribe, and window controls. Every channel is handled in the main process (desktop/ipc/core.ts, auth.ts, workspace.ts). The surface is narrow on purpose and should not be widened for ordinary changes. See Hazards and pitfalls.
User-supplied provider keys are encrypted with AES-256-GCM in lib/crypto.ts. getEncryptionKey reads ENCRYPTION_KEY; a 64-character hex value is used as raw key bytes, any other value is hashed with SHA-256. Each encrypt call uses a fresh 16-byte IV and returns { encrypted, iv, authTag }, all three of which are stored. lib/llm/user-api-keys.ts writes those columns through Prisma (upsertUserProviderKey) and decrypts on demand in resolveProviderApiKey, which falls back to a process env key before throwing MissingProviderApiKeyError. The LOCAL provider needs no key. No .env value is committed; .env.example lists names only.
lib/supabase/public.ts builds a client from the public URL plus anon key for user-scoped calls. lib/supabase/admin.ts builds a separate client from SUPABASE_SERVICE_ROLE_KEY; its header restricts it to admin operations (user management, subscription tier updates) and says never to expose it to the client. It is imported only by lib/billing/subscription-service.ts.
lib/billing/xendit-client.ts verifies inbound webhooks in verifyWebhookToken with timingSafeEqual against XENDIT_CALLBACK_TOKEN, returning false on a length mismatch rather than throwing.
lib/auth/shared-rate-limit.ts buckets counters by time window and hashes the raw key with SHA-256 (hashKey), so no IP or email is stored in clear. Counters live under a unique (action, scope, keyHash, windowStart) constraint; a P2002 race retries rather than double-counts. lib/auth/abuse-protection.ts applies per-IP and per-email rules to register, forgot-password, and resend-verification.
A session without an access_token is shown as a guest badge in desktop/main.ts (buildShellBadges). Guest optimize and evaluate calls route through resolveGuestProvider (lib/llm/provider-readiness.ts) to whichever provider the environment has a key for, never a user key.
| Boundary | Control | Where |
|---|---|---|
| Renderer to Node |
contextIsolation: true, nodeIntegration: false
|
desktop/main.ts |
| Renderer to main | Fixed window.sentraDesktop via contextBridge
|
desktop/preload.ts |
| Provider keys at rest | AES-256-GCM with ENCRYPTION_KEY, per-key IV |
lib/crypto.ts |
| Public vs admin Supabase | Separate anon and service-role clients |
lib/supabase/public.ts, lib/supabase/admin.ts
|
| Xendit webhooks |
timingSafeEqual token check |
lib/billing/xendit-client.ts |
| Auth abuse | Per-IP and per-email limits, SHA-256 key hashing | lib/auth/abuse-protection.ts |
Open-source prompt engineering and multi-LLM tooling by Sentra Artificial Intelligence.
MyPrompt develops practical approaches to prompt engineering, multi-LLM optimisation, reusable prompt systems, and AI-native workflows — with an emphasis on structured, interoperable, and real-world AI use.
Built in Indonesia as part of the Sentra Artificial Intelligence ecosystem.
Sentra Artificial Intelligence · Source Repository · Official Website
Dr Ferdi Iskandar — Creator & Maintainer
LinkedIn ·
ORCID ·
Hugging Face ·
Kaggle ·
Medium ·
Substack ·
X ·
Threads
MyPrompt · Sentra Artificial Intelligence · Indonesia