-
Notifications
You must be signed in to change notification settings - Fork 0
[codex] Enable v0.3 Notion and Postgres onboarding #224
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
2cbcec6
fc3a5ef
c79618f
35b1ecd
67ec2ab
4c5b416
75990c6
d877466
c264e18
665482d
4d9b27b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -478,15 +478,27 @@ const addDataSource = mutation({ | |
| name: text, | ||
| apiKey: text.optional(), | ||
| connectionString: text.optional(), | ||
| config: jsonb.optional(), | ||
| }, | ||
| handler: async ( | ||
| ctx, | ||
| { type, name, apiKey, connectionString }, | ||
| { type, name, apiKey, connectionString, config: rawConfig }, | ||
| ): Promise<{ id: string }> => { | ||
| const vault = vaultFromCtx(ctx); | ||
| // The id is generated by the DB default; use a pre-generated UUID as hint. | ||
| const rowId = crypto.randomUUID(); | ||
| const config: DataSourceConfig = {}; | ||
| if (rawConfig !== undefined && !isRecord(rawConfig)) { | ||
| throw new Error("Data source config must be an object"); | ||
| } | ||
| if ( | ||
| rawConfig && | ||
| ("apiKey" in rawConfig || "connectionString" in rawConfig) | ||
| ) { | ||
| throw new Error( | ||
| "Data source credentials must use typed credential fields, not config", | ||
| ); | ||
| } | ||
| const config: DataSourceConfig = { ...(rawConfig ?? {}) }; | ||
|
Comment on lines
+493
to
+501
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win Blacklist-based credential-smuggling check doesn't scale. The check hardcodes 🤖 Prompt for AI Agents |
||
| // Refs minted in THIS call only — a fresh insert has no pre-existing config, | ||
| // so every ref that lands in `config` here was just minted by this operation. | ||
| const minted: SecretRef[] = []; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; | ||
|
|
||
| import { isPostHogLoaded, loadPostHog, resetPostHogLoader } from "./loader"; | ||
|
|
||
| const config = { | ||
| apiKey: "test-key", | ||
| apiHost: "https://posthog.example.com", | ||
| }; | ||
|
|
||
| describe("PostHog loader lifecycle", () => { | ||
| let idleCallbacks: Array<() => void>; | ||
|
|
||
| beforeEach(async () => { | ||
| await resetPostHogLoader(); | ||
| idleCallbacks = []; | ||
| window.requestIdleCallback = vi.fn((callback) => { | ||
| idleCallbacks.push(() => | ||
| callback({ didTimeout: false, timeRemaining: () => 1 }), | ||
| ); | ||
| return idleCallbacks.length; | ||
| }); | ||
| }); | ||
|
|
||
| afterEach(async () => { | ||
| await resetPostHogLoader(); | ||
| }); | ||
|
|
||
| it("does not initialize a load invalidated while waiting for idle", async () => { | ||
| const staleLoad = loadPostHog(config); | ||
|
|
||
| await resetPostHogLoader(); | ||
| idleCallbacks[0]?.(); | ||
|
|
||
| await expect(staleLoad).rejects.toThrow("PostHog load was cancelled"); | ||
| expect(isPostHogLoaded()).toBe(false); | ||
| }); | ||
| }); |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| **Comparison Target** | ||
|
|
||
| - Source visual truth path: `/Users/youhaowei/.codex/visualizations/2026/07/09/019f4916-5845-7540-ab74-293e68c37230/insight-section-navigator-wireframe.html` | ||
| - Implementation URL: `https://v0-3-remote-onboarding.dashframe.localhost/insights/cafd95a3-9073-43f9-ae80-ccef86a512f3?visualize=false` | ||
| - Implementation screenshots: `/tmp/dashframe-insight-data.png`, `/tmp/dashframe-insight-visualize.png` | ||
| - Viewport: 1280 × 720 at 2× device pixel ratio | ||
| - State: existing joined insight, light theme; Data and Visualize output modes; Model, Fields, Metrics, Filters, and Sort modeling sections | ||
|
|
||
| **Findings** | ||
|
|
||
| - No actionable P0/P1/P2 issue remains in the browser-rendered implementation. | ||
| - [P3] Long generated table names truncate inside the compact model cards. The source mock uses shorter human-readable names; the implementation preserves the real dataset names and exposes source actions. This is acceptable for the current data fixture. | ||
|
|
||
| **Required Fidelity Surfaces** | ||
|
|
||
| - Fonts and typography: existing DashFrame typography tokens and weights are preserved; section hierarchy and compact labels remain readable at the target viewport. | ||
| - Spacing and layout rhythm: the left section navigator remains fixed while only the selected editor scrolls; compact model cards replace the oversized source cards; Data and Visualize controls occupy a stable header region. | ||
| - Colors and visual tokens: implementation uses existing neutral, border, emphasis, primary, and chart-series tokens. | ||
| - Image quality and asset fidelity: no raster imagery is required. Existing connector and chart icons are used; connector icons render at 12–16 px without scaling artifacts. | ||
| - Copy and content: Data is labeled as the canonical result, chart types appear only in Visualize, and every modeling section uses task-specific explanatory copy. | ||
|
|
||
| **Interaction Evidence** | ||
|
|
||
| - Model, Fields, Metrics, Filters, and Sort navigation buttons were clicked and each displayed only its corresponding editor. | ||
| - Data displayed the canonical result table without chart-type controls. | ||
| - Visualize selected an available chart, displayed chart-type controls, and removed the result table from the canvas. | ||
| - Sort uses the persisted `Insight.sorts` contract; its Add action is disabled when no selected field or metric can be sorted. | ||
| - No visible runtime error state appeared. Type checking, linting, and focused component tests cover the changed implementation. | ||
|
|
||
| **Comparison History** | ||
|
|
||
| - Initial P1: compact model cards inherited an inline connector icon whose SVG expanded to 300 × 300 px. Fixed by giving the connector wrapper an explicit inline-block formatting context. Post-fix browser measurement: 16 × 16 px icon and 104 px card height. | ||
| - Initial P2: five modeling sections were compressed into one row and their labels truncated. Fixed by using a wrapping fixed navigator with approximately 7 rem per item. Post-fix browser evidence shows full Model, Fields, Metrics, Filters, and Sort labels with counts. | ||
|
|
||
| **Full-view Comparison Evidence** | ||
|
|
||
| - Browser captures confirm the intended two-region workspace, fixed modeling navigator, compact model editor, canonical Data result, and separate Visualize chart chooser. | ||
| - The source HTML was rendered to `/tmp/insight-section-navigator-reference.html`, but the selected in-app browser rejected opening the local file under its URL security policy. A combined source-and-implementation screenshot could therefore not be produced in the permitted browser surface. | ||
|
|
||
| **Focused Region Comparison Evidence** | ||
|
|
||
| - Left model region was measured in the browser after the icon fix: compact source card 224 × 104 px, connector icon 16 × 16 px. | ||
| - A combined focused comparison is blocked by the same source-capture restriction above. | ||
|
|
||
| **Open Questions** | ||
|
|
||
| - None for implementation behavior. The remaining blocker is evidence capture, not a known product defect. | ||
|
|
||
| **Implementation Checklist** | ||
|
|
||
| - [x] Fixed section navigator for Model, Fields, Metrics, Filters, and Sort | ||
| - [x] One modeling editor visible at a time | ||
| - [x] Compact table and join cards in the left panel | ||
| - [x] Functional persisted sort editor | ||
| - [x] Separate Data and Visualize output modes | ||
| - [x] Chart types removed from the canonical Data result | ||
| - [x] Browser interaction pass at the target route | ||
| - [ ] Combined source and implementation comparison in the same visual input | ||
|
|
||
| **Follow-up Polish** | ||
|
|
||
| - Consider shorter display aliases for generated table names independently of this workspace redesign. | ||
|
|
||
| final result: blocked |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When a client sends connector config with a nested or alternate credential value, such as
{ nested: { connectionString: "postgres://..." } }or{ dsn: "postgres://..." }, this spread persists it directly indata_sources.config;rowToDataSourcethen forwards non-credential config keys back to the renderer. That bypasses the new top-level smuggling guard and breaks the plaintext-never-at-rest/no-secret-in-DTO invariant for any buggy or untrusted caller ofaddDataSource; whitelist expected non-secret keys likedefaultSchemaor recursively reject credential-shaped data before copying config.Useful? React with 👍 / 👎.