diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index aa60cfcde..5603020f5 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -5,8 +5,6 @@ updates:
schedule:
interval: "weekly"
open-pull-requests-limit: 10
- reviewers:
- - "louis030195"
labels:
- "dependencies"
- "security"
diff --git a/.gitignore b/.gitignore
index 0e193043f..71b2669bc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -202,3 +202,6 @@ apps/desktop/apps/vm-dashboard/public/*.zip
# internal ops runbooks, not for public repo
.claude/skills/
+
+# Local-only backups of deleted GitHub issues (may contain sensitive content)
+scripts/deleted-issues-backup/
diff --git a/README.md b/README.md
index 55d5b7f4f..06806af56 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,65 @@
-
+
+
+# Mediar
+
+Capture a browser workflow once, then run it on demand against cloud VMs. Mediar records what you do in the browser, turns it into a reusable workflow, and executes it headlessly through MCP-driven virtual machines.
+
+Live app: [app.mediar.ai](https://app.mediar.ai)
+
+## Monorepo layout
+
+| Path | What it is |
+|------|------------|
+| `apps/web` | Next.js 15 web app (dashboard, auth, billing, workflow management) |
+| `apps/desktop` | Tauri desktop app (React + Rust) for capturing workflows |
+| `crates/executor` | Rust workflow executor |
+| `modal_apps` | Python executor deployed on [Modal](https://modal.com) |
+| `packages/infra` | Azure / telemetry utilities |
+| `supabase` | Database schema and migrations |
+
+## Architecture
+
+```
+GitHub workflows repo → Modal / Rust executor → MCP VMs → Supabase
+```
+
+Workflows are stored in a repo, dispatched to the Modal or Rust executor, run on MCP-controlled VMs, and results are persisted to Supabase.
+
+## Quick start
+
+Requires [Bun](https://bun.sh) and Node 20 (see `.nvmrc`).
+
+```bash
+bun install
+cp .env.example .env.local # fill in your own keys
+bun run dev # run all packages
+```
+
+Useful scripts:
+
+```bash
+bun run dev:web # web app only
+bun run dev:desktop # desktop app only (Tauri)
+bun run build # build everything
+bun run type-check # typecheck all packages
+bun run test # run all tests
+```
+
+## Deploy
+
+```bash
+# Python executor (Modal)
+export PYTHONIOENCODING=utf-8 && modal deploy modal_apps/workflow_executor.py
+
+# Rust executor
+bun run deploy:rust # dev
+bun run deploy:rust:prod # prod
+```
+
+## Contributing
+
+Issues and pull requests are welcome. Run `bun run type-check` and `bun run test` before opening a PR.
+
+## License
+
+[MIT](./LICENSE)
diff --git a/apps/desktop/scripts/release.ts b/apps/desktop/scripts/release.ts
index 59a72a63b..da9373caa 100644
--- a/apps/desktop/scripts/release.ts
+++ b/apps/desktop/scripts/release.ts
@@ -11,7 +11,7 @@
* ============================================
*
* 1. SSL.com Credentials (~\SSL.com\.env)
- * - Get the .env file from Louis or another team member
+ * - Get the .env file from a team member
* - Place at: C:\Users\\SSL.com\.env
* - Or set MEDIAR_SSL_DIR env var to custom location
* - Required variables:
diff --git a/apps/web/src/app/api/admin/cost-alerts/route.ts b/apps/web/src/app/api/admin/cost-alerts/route.ts
index e0780035c..d41d1602b 100644
--- a/apps/web/src/app/api/admin/cost-alerts/route.ts
+++ b/apps/web/src/app/api/admin/cost-alerts/route.ts
@@ -61,7 +61,7 @@ export async function GET() {
// Return existing settings or defaults
const settings: CostAlertSettings = data?.value || {
thresholds: DEFAULT_THRESHOLDS,
- emailRecipients: ['matt@mediar.ai', 'louis@mediar.ai'],
+ emailRecipients: ['matt@mediar.ai'],
enabled: true,
};
diff --git a/apps/web/src/app/api/admin/organizations/[orgId]/members/route.ts b/apps/web/src/app/api/admin/organizations/[orgId]/members/route.ts
index 886e20405..c64140e9f 100644
--- a/apps/web/src/app/api/admin/organizations/[orgId]/members/route.ts
+++ b/apps/web/src/app/api/admin/organizations/[orgId]/members/route.ts
@@ -38,18 +38,9 @@ export async function GET(
organization: {
id: targetOrgId,
name: 'Mediar (Legacy/Dev)',
- membersCount: 2
+ membersCount: 1
},
members: [
- {
- id: 'legacy-1',
- userId: 'mediar-admin-1',
- email: 'louis@mediar.ai',
- firstName: 'Louis',
- lastName: 'Beaumont',
- role: 'org:admin',
- createdAt: new Date().toISOString()
- },
{
id: 'legacy-2',
userId: 'mediar-admin-2',
diff --git a/apps/web/src/app/api/cron/llm-usage-reconciliation/route.ts b/apps/web/src/app/api/cron/llm-usage-reconciliation/route.ts
index 6aa8b9ff4..3211644e0 100644
--- a/apps/web/src/app/api/cron/llm-usage-reconciliation/route.ts
+++ b/apps/web/src/app/api/cron/llm-usage-reconciliation/route.ts
@@ -108,7 +108,7 @@ async function sendDiscrepancyAlert(details: {
return;
}
- const recipients = ['matt@mediar.ai', 'louis@mediar.ai'];
+ const recipients = ['matt@mediar.ai'];
const subject = `LLM Token Discrepancy: API ${(details.googleTokens/1e6).toFixed(1)}M vs Traced ${(details.dbTokens/1e6).toFixed(1)}M (${details.discrepancyPercent.toFixed(1)}% diff)`;
const body = `
LLM token usage reconciliation detected a significant discrepancy:
diff --git a/apps/web/src/app/api/cron/process-pending-notifications/route.ts b/apps/web/src/app/api/cron/process-pending-notifications/route.ts
index 74a7bd764..f6db277e5 100644
--- a/apps/web/src/app/api/cron/process-pending-notifications/route.ts
+++ b/apps/web/src/app/api/cron/process-pending-notifications/route.ts
@@ -11,7 +11,7 @@ async function getOrganizationMembers(orgId: string): Promise {
try {
// Handle legacy Mediar org (members not in Clerk; fall back to staff).
if (isLegacyOrg(orgId)) {
- return ['louis@mediar.ai', 'matt@mediar.ai'];
+ return ['matt@mediar.ai'];
}
const clerk = await clerkClient();
diff --git a/apps/web/src/app/api/internal/notifications/alerts/route.ts b/apps/web/src/app/api/internal/notifications/alerts/route.ts
index a10c4901e..5fd6967bc 100644
--- a/apps/web/src/app/api/internal/notifications/alerts/route.ts
+++ b/apps/web/src/app/api/internal/notifications/alerts/route.ts
@@ -21,7 +21,7 @@ async function getOrganizationMembers(orgId: string): Promise {
// Handle legacy Mediar org (members not in Clerk; fall back to staff).
if (isLegacyOrg(orgId)) {
- return ['louis@mediar.ai', 'matt@mediar.ai'];
+ return ['matt@mediar.ai'];
}
const clerk = await clerkClient();
diff --git a/apps/web/src/app/api/internal/send-notification-email/route.ts b/apps/web/src/app/api/internal/send-notification-email/route.ts
index ec578fa96..047f8e1ff 100644
--- a/apps/web/src/app/api/internal/send-notification-email/route.ts
+++ b/apps/web/src/app/api/internal/send-notification-email/route.ts
@@ -62,7 +62,7 @@ export async function POST(request: NextRequest) {
// Send email using Resend
const { data, error } = await resend.emails.send({
from: `Mediar.ai <${fromEmail}>`,
- replyTo: ['matt@mediar.ai', 'louis@mediar.ai'],
+ replyTo: ['matt@mediar.ai'],
to: Array.isArray(to) ? to : [to],
subject: enhancedSubject,
html: emailHtml,
@@ -476,7 +476,7 @@ function generateEmailHTML(alert: any, _config: any): string {