Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# EditorConfig — https://editorconfig.org
# Keeps editor defaults in lockstep with .prettierrc (printWidth 120, 2-space)
# and .gitattributes (`* text=auto eol=lf`). Editor-only; formatting is still
# enforced by Prettier — this just stops editors introducing CRLF / tab / stray
# trailing-whitespace churn before Prettier runs.
root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = space
indent_size = 2

# Markdown: two trailing spaces are a meaningful hard line break, so do not strip them.
[*.md]
trim_trailing_whitespace = false

# Generated by `supabase gen types`; keep the generator's formatting (also
# prettier-ignored in .prettierignore) so regeneration stays churn-free.
[src/lib/supabase/database.types.ts]
trim_trailing_whitespace = false
insert_final_newline = false
24 changes: 24 additions & 0 deletions .githooks/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/bin/sh
# Pre-commit hook: auto-format and lint staged files.
# Installed by scripts/install-git-hooks.mjs via `git config core.hooksPath .githooks`.
#
# Set GUARD_PRECOMMIT_DISABLE=1 to bypass (e.g. for emergency commits).
set -eu

if [ "${GUARD_PRECOMMIT_DISABLE:-}" = "1" ]; then
exit 0
fi

# Resolve node; if unavailable, skip gracefully rather than block commits.
if ! command -v node >/dev/null 2>&1; then
echo "[pre-commit] node not found on PATH — skipping lint-staged" >&2
exit 0
fi

# Resolve npx; likewise skip rather than block.
if ! command -v npx >/dev/null 2>&1; then
echo "[pre-commit] npx not found on PATH — skipping lint-staged" >&2
exit 0
fi

npx lint-staged

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '--- .githooks/pre-commit ---\n'
cat -n .githooks/pre-commit

printf '\n--- package.json ---\n'
cat -n package.json

printf '\n--- lockfiles / package manager hints ---\n'
git ls-files | rg '(^|/)(package-lock\.json|pnpm-lock\.yaml|yarn\.lock|bun\.lockb|npm-shrinkwrap\.json)$|(^|/)\.npmrc$|(^|/)\.yarnrc(\.yml)?$'

Repository: BigSimmo/Database

Length of output: 246


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- .githooks/pre-commit ---'
cat -n .githooks/pre-commit

echo
echo '--- package.json ---'
cat -n package.json

echo
echo '--- lockfiles / package manager hints ---'
git ls-files | rg '(^|/)(package-lock\.json|pnpm-lock\.yaml|yarn\.lock|bun\.lockb|npm-shrinkwrap\.json)$|(^|/)\.npmrc$|(^|/)\.yarnrc(\.yml)?$'

Repository: BigSimmo/Database

Length of output: 15456


🌐 Web query:

npm 11 npx --no-install npm exec --no-install local binary missing install from registry behavior

💡 Result:

In npm 11 (as well as all versions since npm v7), the behavior of npx and npm exec has been standardized around the npm exec command [1][2][3]. Regarding your specific query: 1. Deprecation of --no-install: The --no-install option is deprecated and is automatically converted to --no [1][2][4]. 2. Behavior with --no: When you use --no (or the deprecated --no-install), npm is explicitly instructed not to attempt to install any missing packages from the registry [2][3][5]. 3. Handling of Local Binaries: - By design, npx and npm exec include locally installed package executables in the PATH of the executed command [1][6][7]. - If a binary is already present in your project's local dependencies (e.g., in node_modules/.bin), it should be found and executed correctly regardless of the --no flag [1][3]. - If the binary is missing from the local dependencies and you use --no, npm exec will fail because it is prohibited from installing the package from the registry to resolve the command [2][5][8]. If you find that a locally available binary is not being detected when using --no, it may be related to specific configuration issues, such as workspace contexts or how the binary is defined in package.json [9]. If the binary is not part of the project's dependency tree, npm cannot execute it without performing an installation, which the --no flag prevents [2][3].

Citations:


Prevent npx from installing lint-staged here. Use npx --no lint-staged (or npm exec --no lint-staged) so a missing local binary fails instead of fetching an unpinned package from the registry.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.githooks/pre-commit at line 24, Update the lint-staged invocation in the
pre-commit hook to use npx --no (or npm exec --no), ensuring it only runs the
locally installed lint-staged binary and fails when unavailable instead of
installing from the registry.

Empty file modified .githooks/pre-push
100644 → 100755
Empty file.
39 changes: 39 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# CODEOWNERS — https://docs.github.com/articles/about-code-owners
#
# This repo is currently single-maintainer, so every path resolves to the same
# owner. The value here is intent + automatic review routing on the high-risk
# surfaces called out in AGENTS.md (auth, migrations/RLS, RAG/retrieval, source
# governance, clinical output, production config). As collaborators join, add
# them to the specific sections below rather than only the catch-all.
#
# Later patterns win, so the catch-all comes first and high-risk paths override it.

# Catch-all
* @BigSimmo

# Database / migrations / RLS (destructive-change surface)
/supabase/ @BigSimmo

# Environment + security header contract
/src/lib/env.ts @BigSimmo
/src/lib/client-env.ts @BigSimmo
/src/lib/security-headers.ts @BigSimmo
/src/proxy.ts @BigSimmo
/src/instrumentation.ts @BigSimmo
/src/instrumentation-client.ts @BigSimmo

# RAG / retrieval / search / ranking
/src/lib/rag.ts @BigSimmo
/src/lib/rag-*.ts @BigSimmo
/src/lib/retrieval-*.ts @BigSimmo
/src/lib/*search*.ts @BigSimmo
/src/lib/privacy.ts @BigSimmo
/src/lib/query-privacy.ts @BigSimmo

# Source governance + clinical output
/scripts/audit-source-governance.ts @BigSimmo
/scripts/*governance*.ts @BigSimmo
/docs/clinical-governance.md @BigSimmo

# CI / release automation
/.github/workflows/ @BigSimmo
4 changes: 4 additions & 0 deletions .lintstagedrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}": ["prettier --write --ignore-unknown", "eslint --fix"],
"*.{json,md,yml,yaml,css,scss}": ["prettier --write --ignore-unknown"]
}
8 changes: 8 additions & 0 deletions .size-limit.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[
{
"name": "Client JS — all route/chunk bundles (gzip)",
"path": ".next/static/chunks/**/*.js",
"limit": "1300 KB",
"gzip": true
}
]
1 change: 1 addition & 0 deletions docs/site-map.md
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,7 @@ This file is generated by `npm run sitemap:update`. Run `npm run sitemap:check`
- `/api/local-project-id` - Local project identity guard. Source: `src/app/api/local-project-id/route.ts`.
- `/api/medications` - Route discovered from app directory Source: `src/app/api/medications/route.ts`.
- `/api/medications/[slug]` - Route discovered from app directory Source: `src/app/api/medications/[slug]/route.ts`.
- `/api/monitoring` - Route discovered from app directory Source: `src/app/api/monitoring/route.ts`.
- `/api/registry/records` - Registry record collection. Source: `src/app/api/registry/records/route.ts`.
- `/api/registry/records/[slug]` - Registry record detail. Source: `src/app/api/registry/records/[slug]/route.ts`.
- `/api/search` - Search endpoint. Source: `src/app/api/search/route.ts`.
Expand Down
20 changes: 20 additions & 0 deletions knip.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"$schema": "https://unpkg.com/knip@6/schema.json",
"entry": [
"src/instrumentation.ts",
"src/instrumentation-client.ts",
"src/proxy.ts",
"scripts/**/*.{ts,mjs,cjs}",
"worker/**/*.ts",
"playwright/**/*.ts",
"eslint-rules/**/*.mjs",
"tests/**/*.{test.ts,dom.test.tsx,spec.ts}",
"*.config.{ts,mts,mjs,cjs}"
],
"project": ["src/**/*.{ts,tsx}", "scripts/**/*.{ts,mjs,cjs}", "worker/**/*.ts", "eslint-rules/**/*.mjs"],
"ignore": ["src/lib/supabase/database.types.ts", "**/*mockup*", "src/app/mockups/**", "supabase/functions/**"],
"ignoreDependencies": ["tailwindcss", "server-only"],
"ignoreBinaries": ["supabase", "semgrep", "gitleaks", "taskkill"],
"vitest": { "config": ["vitest.config.mts"] },
"playwright": { "config": ["playwright.config.ts", "playwright.visual.config.ts"] }
}
36 changes: 34 additions & 2 deletions next.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,27 @@ async function withOptionalBundleAnalyzer(config: NextConfig): Promise<NextConfi
return bundleAnalyzer({ enabled: true })(config);
}

// Gated Sentry build integration. Only wraps the config when a DSN is present, so
// a build WITHOUT Sentry configured is byte-for-byte unchanged (no plugin, no
// source-map step). Source-map upload additionally requires SENTRY_ORG/PROJECT/
// AUTH_TOKEN; without them the plugin still runs but silently skips upload. The
// runtime SDK is initialised separately in src/instrumentation*.ts.
async function withOptionalSentry(config: NextConfig): Promise<NextConfig> {
if (!process.env.SENTRY_DSN && !process.env.NEXT_PUBLIC_SENTRY_DSN) return config;
const { withSentryConfig } = await import("@sentry/nextjs");
return withSentryConfig(config, {
org: process.env.SENTRY_ORG,
project: process.env.SENTRY_PROJECT,
authToken: process.env.SENTRY_AUTH_TOKEN,
silent: !process.env.CI,
// We hand-roll the tunnel route (src/app/api/monitoring/route.ts), so the SDK
// must not also auto-generate one.
tunnelRoute: false,
// Keep the client bundle lean; upload is opt-in via SENTRY_AUTH_TOKEN.
sourcemaps: { disable: !process.env.SENTRY_AUTH_TOKEN },
}) as NextConfig;
}

const nextConfig: NextConfig = {
// Playwright and some local tooling hit the dev server via 127.0.0.1; without
// this, Next blocks HMR/client hydration from that host and phone scroll-hide
Expand All @@ -36,12 +57,23 @@ const nextConfig: NextConfig = {
turbopack: {
root: projectRoot,
},
webpack(config) {
webpack(config, { webpack }) {
// Avoid a Next/webpack WasmHash worker crash observed on Node 24 during local production builds.
config.output = {
...config.output,
hashFunction: "sha256",
};
// Build-time flag so the client Sentry SDK is fully tree-shaken out unless a
// public DSN is set at build time. Next does NOT fold an UNSET NEXT_PUBLIC_*
// var to a compile-time constant, so a plain `if (process.env.NEXT_PUBLIC_SENTRY_DSN)`
// gate leaves the (large) dynamic import in the graph and its chunk on disk.
// This literal boolean lets webpack dead-code-eliminate the whole block, so an
// unconfigured build ships zero Sentry bytes. See src/instrumentation-client.ts.
config.plugins.push(
new webpack.DefinePlugin({
__SENTRY_ENABLED__: JSON.stringify(Boolean(process.env.NEXT_PUBLIC_SENTRY_DSN)),
}),
);
return config;
},
async headers() {
Expand All @@ -54,4 +86,4 @@ const nextConfig: NextConfig = {
},
};

export default withOptionalBundleAnalyzer(nextConfig);
export default withOptionalBundleAnalyzer(nextConfig).then(withOptionalSentry);
Loading