Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
9aad99c
feat(clipping): YouTube video clipping workflow with REST, MCP tools …
nevo-david Sep 19, 2026
f5d83b1
fix(clipping): close the clip and draft creation races from review
nevo-david Sep 19, 2026
c7405ff
fix(clipping): never give a draft claim back, draft one channel at a …
nevo-david Sep 19, 2026
523aace
Merge remote-tracking branch 'origin/main' into feat/clipping-workflow
nevo-david Sep 19, 2026
6f10780
Merge pull request #2104 from gitroomhq/feat/clipping-workflow
nevo-david Sep 19, 2026
7cef69c
feat(security): enhance GAdvisory scope
egelhaus Sep 20, 2026
373ebb1
docs: minimal batch groundwork - ADR-0001 upstream sync policy, fork-…
JOY Sep 21, 2026
03e4f51
Merge remote-tracking branch 'upstream/main' into upstream-sync-20260921
JOY Sep 21, 2026
33ffb60
docs: address review - verifiable integration count, correct zustand …
JOY Sep 21, 2026
30357f3
chore(sync): drop dead crove_post_ hidden-tool aliases for clipping t…
JOY Sep 21, 2026
616bb04
fix(sync): use fork OpenAI client pattern in upstream pickClips
JOY Sep 21, 2026
665e93a
chore(lint): migrate to eslint 9 and typescript-eslint 8
JOY Sep 21, 2026
f75545d
fix(sync): clear CodeQL high alerts in synced clipping and local stor…
JOY Sep 21, 2026
5ad573b
fix(sync): path.relative containment check in LocalStorage.removeFile
JOY Sep 21, 2026
9878495
docs: record 2026-09-21 sync security fixes in fork-delta inventory
JOY Sep 21, 2026
ec30990
docs: correct integration count to 35 (one list entry is commented out)
JOY Sep 21, 2026
fca0520
Merge pull request #42 from DOS/docs/refactor-batch-1
JOY Sep 21, 2026
a42c753
Merge pull request #44 from DOS/chore/eslint-9
JOY Sep 21, 2026
b8d7778
Merge pull request #43 from DOS/upstream-sync-20260921
JOY Sep 21, 2026
ca706b2
test(frontend): vitest + testing-library baseline for form primitives
JOY Sep 21, 2026
f742d9f
test(frontend): address review - real checked-state assertions, hones…
JOY Sep 21, 2026
e873a73
Merge pull request #45 from DOS/test/frontend-baseline
JOY Sep 21, 2026
eb219c2
test(e2e): playwright smoke harness + prod compose reconciliation doc
JOY Sep 21, 2026
ba797f7
docs(ops): do not spell out the dev-default temporal password value
JOY Sep 21, 2026
4a51778
Merge pull request #46 from DOS/test/e2e-smoke
JOY Sep 21, 2026
8ed4f3e
chore(ops): Phase B corrections to prod compose after live execution
JOY Sep 21, 2026
11f4a09
Merge pull request #47 from DOS/chore/phaseb-compose-fixes
JOY Sep 21, 2026
729be04
chore(ci): one-off workflow to dismiss CodeQL alert 1567 via GITHUB_T…
JOY Sep 21, 2026
fd2818a
Merge pull request #48 from DOS/chore/oneoff-dismiss-alert
JOY Sep 21, 2026
eea922a
chore(ci): debug GET before PUT in oneoff dismissal
JOY Sep 21, 2026
e49a382
Merge pull request #49 from DOS/chore/oneoff-dismiss-alert
JOY Sep 21, 2026
0199f49
chore(ci): remove one-off CodeQL dismissal workflow
JOY Sep 21, 2026
555b7b8
Merge pull request #50 from DOS/chore/remove-oneoff-workflow
JOY Sep 21, 2026
467a500
fix(billing): unwrap dos.me { success, data } response envelope
JOY Sep 21, 2026
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
22 changes: 22 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,28 @@ EXCLUDE_QUEUE=""
# Concurrency divider for worker task allocation (default: 1)
WORKER_CONCURRENCY_DIVIDER="1"

## Remember to set your public internet IP address in the allow-list for the API token.
##
## Cloudflare is currently required to save things like social media avatars for accounts.
CLOUDFLARE_ACCOUNT_ID="your-account-id"
CLOUDFLARE_ACCESS_KEY="your-access-key"
CLOUDFLARE_SECRET_ACCESS_KEY="your-secret-access-key"
CLOUDFLARE_BUCKETNAME="your-bucket-name"
CLOUDFLARE_BUCKET_URL="https://your-bucket-url.r2.cloudflarestorage.com/"
CLOUDFLARE_REGION="auto"
## Optional media normalization (postiz-uploader on RunPod Serverless). Requires STORAGE_PROVIDER="cloudflare".
## When set, web uploads are transcoded to 1080p h264 mp4 / downsized images in the background;
## the media record reports status "processing" until the normalized file replaces the original.
#RUNPOD_API_KEY=""
#RUNPOD_ENDPOINT_ID=""
## Optional video clipping (YouTube video -> captioned vertical clips -> draft posts). Requires STORAGE_PROVIDER="cloudflare",
## RUNPOD_API_KEY (with access to both endpoints below) and OPENAI_API_KEY. Ingest jobs go to the CPU endpoint, clip jobs to the
## GPU endpoint of postiz-uploader (which needs its own Oxylabs account to fetch from YouTube); Deepgram transcribes videos
## that have no usable captions.
#RUNPOD_INGEST_ENDPOINT_ID=""
#RUNPOD_CLIPPER_ENDPOINT_ID=""
#DEEPGRAM_API_KEY=""

# ==============================================================================
# 4. Storage Providers (Cloudflare R2 or Local Disk)
# ==============================================================================
Expand Down
1 change: 0 additions & 1 deletion .eslintignore

This file was deleted.

3 changes: 3 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,5 +90,8 @@ jobs:
# known ids, so they must not run concurrently against each other.
run: pnpm exec jest --config tests/bootstrap.jest.cjs --ci --passWithNoTests --runInBand

- name: Test frontend primitives (vitest)
run: pnpm run test:frontend

- name: Build applications
run: pnpm run build
2 changes: 1 addition & 1 deletion .github/workflows/eslint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ jobs:

- name: Install ESLint SARIF Formatter
run: |
pnpm add -D @microsoft/eslint-formatter-sarif@2.1.7
pnpm add -D @microsoft/eslint-formatter-sarif@3.1.0

- name: Run ESLint
# Transitional: violations are now VISIBLE as a failed step instead of
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,7 @@ scripts/*.env
.playwright-mcp/
.cloudflared/


# playwright
playwright-report/
test-results/
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Changed
- **ESLint Workflow Green via eslint 9 Migration**:
- Bumped eslint 8.57 -> ^9 and @typescript-eslint/* 7.18 -> ^8; the ESLint workflow had been red because eslint 8 cannot parse the flat `eslint.config.mjs`, so eslint crashed before producing the SARIF file.
- CI SARIF formatter moved to `@microsoft/eslint-formatter-sarif@3.1.0`; dead `.eslintignore` removed (eslint 9 ignores node_modules by default). Flat config unchanged; violations stay visible through the SARIF upload under the transitional `continue-on-error` gate (audit C9).

### Fixed
- **Customer-Facing UI, SDK and MCP Announcing Upstream Infrastructure (Upstream Endpoint Leaks)**:
- Root cause: the Branding Guard scanned only AGPL attribution (repo, image, author), so it reported "0 strict branding leaks" while runtime endpoints still pointed at upstream infrastructure.
Expand All @@ -28,6 +33,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Beta container recreated with the same immutable image digest; a one-off boot hang after recreate (backend blocked pre-Nest with no network sockets) was cleared by a plain `docker restart`.

### Added
- **Prod Compose Phase B Executed on crove-server (2026-09-21, JOY approved)**:
- Installed `scripts/docker-compose.prod.yaml` at `/opt/crove` (backups kept), recreated crove-post / crove-redis / cloudflared with the I-B4 image pin + healthcheck; crove-post reports `healthy`.
- Adopted the S18 healthchecks across the Temporal stack: temporal, temporal-postgresql and temporal-elasticsearch all report `healthy`; functional proof via tctl after every step.
- Rotated `CROVE_TEMPORAL_POSTGRES_PASSWORD` from the well-known dev default to a 32-char random secret (env files + DB role updated together; temporal reconnects with the new password).
- Removed the legacy `crove-postgres` and `postiz-redis` containers (prod verified on Supabase + `crove-redis`; volumes retained).
- Two evidence-based corrections merged back into `scripts/docker-compose.prod.yaml`: dynamicconfig stays `development-sql.yaml` (the auto-setup image ships no production template and `./dynamicconfig` shadows the image dir), and the temporal healthcheck probes `$(hostname -i)` instead of localhost (the server binds the container IP - localhost probes reported `unhealthy` while the server was fine).
- `docs/ops/prod-compose-reconciliation.md` updated from "plan" to "executed" with deviations and residual items (pg_hba trust rows internal-only, `crove_postgres-volume` kept 2 weeks, crove-web dormant).
- **Frontend Test Track (Minimal Batch)**:
- Added a vitest + Testing Library baseline for shared form primitives (`vitest.frontend.config.ts`, `tests/frontend/`, `pnpm run test:frontend`, CI step in `build.yml`): 14 tests over Button, Textarea and Checkbox. Frontend previously had zero tests.
- Added a Playwright smoke E2E harness (`playwright.config.ts`, `tests/e2e/`, `pnpm run test:e2e`): public checks (auth redirect, Crove branding, DOS ID presence, login page) verified against beta; the authenticated compose -> schedule -> calendar flow is scaffolded and activates with `E2E_DOS_EMAIL` / `E2E_DOS_PASSWORD` once a dedicated beta test account exists. Not wired into CI yet.
- Added `docs/ops/prod-compose-reconciliation.md` cataloging the prod compose drift on `crove-server` (repo audit hardening vs the older VM deploy copy, legacy `crove-postgres` / `postiz-redis` remnants) and the ordered maintenance-window plan.
- **Refactor Documentation Suite (Minimal Batch)**:
- Added `docs/adr/0001-upstream-sync-and-fork-delta.md` recording the verified upstream-sync policy: the pnpm/App Router/SWR+Zustand structure originated upstream (commit `4ba51565` is contained in `upstream/main`), so the daily sync corridor stays open for both backend and frontend.
- Added `docs/fork-delta.md` inventorying every deliberate fork divergence (owned paths, diverging shared files, planned divergence, frozen contracts).
- Added `docs/refactor/minimal-batch.md` (approved 2026-09-21) plus its Vietnamese dark-theme reading copy `docs/refactor/minimal-batch-vi.html`: foundation safety (upstream sync, eslint 9 CI green, crove-sso leftovers, prod compose drift) and test/docs baseline (Playwright smoke, Vitest baseline, CLAUDE.md corrections).
- **MCP Client Icons & Onboarding Enhancements (Upstream Sync)**:
- Added Nanoclaw and other third-party MCP client icons support in Public API.
- Upgraded onboarding experience and interactive modal walkthroughs.
Expand Down
103 changes: 59 additions & 44 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,48 +1,31 @@
This project is Postiz, a tool to schedule social media and chat posts to 28+ channels.
This project is **Crove Post** (`@crove/*`), a fork of [Postiz](https://github.com/gitroomhq/postiz-app) (AGPL-3.0) that schedules social media posts through 35 provider integrations (see `libraries/nestjs-libraries/src/integrations/integration.manager.ts`).
You can add posts to the calendar, they will be added into a workflow and posted at the right time.
You can find things like:
- Schedule posts
- Calendar view
- Analytics
- Team management
- Media library

This project is a monorepo with a root only package.json of dependencies.
Made with PNPM.
We have 3 important folders

- apps/backend - this is where the API code is (NESTJS)
- apps/orchestrator - this is temporal, it's for background jobs (NESTJS) it contains all the workflows and activities
- apps/frontend - this is the code of the frontend (Vite ReactJS)
- /libraries contains a lot of services shared between backend and orchestrator and frontend components.

We are using only pnpm, don't use any other dependency manager.
Never install frontend components from npmjs, focus on writing native components.

The project uses tailwind 3, before writing any component look at:
- /apps/frontend/src/app/colors.scss
- /apps/frontend/src/app/global.scss
- /apps/frontend/tailwind.config.js
Fork-specific surfaces (not in upstream): DOS ID SSO (`api.dos.me`), DOS shared billing (`libraries/nestjs-libraries/src/dos-billing`), runtime branding engine (`libraries/helpers/src/utils/brand.config.ts` + `scripts/branding-guard.ts`), DOS ecosystem sync / first-party bootstrap (`apps/backend/src/ecosystem`), and the `apps/web` marketing site. Everything else intentionally tracks upstream. See `docs/adr/0001-upstream-sync-and-fork-delta.md` and `docs/fork-delta.md`.

All the --color-custom* are deprecated, don't use them.
This project is a monorepo with a root-only package.json of dependencies.
Made with PNPM. We are using only pnpm, don't use any other dependency manager.
Never install frontend components from npmjs, focus on writing native components.

And check other components in the system before to get the right design.
## Layout

When working on the backend we need to pass the 3 layers:
DTO >> Controller >> Service >> Repository (no shortcuts)
In some cases we will have
DTO >> Controller >> Manager >> Service >> Repository.
- apps/backend - NestJS API. Controllers are thin; most logic lives in libraries.
- apps/orchestrator - NestJS Temporal worker: workflows, activities, signals.
- apps/frontend - Next.js 16 App Router dashboard (React 19, port 4200). This is Next.js, not Vite.
- apps/web - fork-owned Next.js marketing site.
- apps/extension - Chrome MV3 extension (Vite + crxjs).
- apps/sdk - published public SDK (`@crove/node`, built with tsup).
- apps/commands - NestJS CLI commands.
- libraries/nestjs-libraries - shared backend services: database (Prisma), integrations, uploads, billing, dos-billing, ecosystem, temporal, chat/MCP.
- libraries/react-shared-libraries - shared frontend primitives: form controls, toaster, translation.
- libraries/helpers - shared utils (`custom.fetch`, `brand.config`, `ecosystem.config`).

Most of the server logic should be inside of libs/server.
The backend repository is mostly used to write controller, and import files from libs.server.
## Frontend

For the frontend follow this:
- Many of the UI components lives in /apps/frontend/src/components/ui
- Routing is in /apps/frontend/src/app
- Components are in /apps/frontend/src/components
- always use SWR to fetch stuff, and use "useFetch" hook from /libraries/helpers/src/utils/custom.fetch.tsx
- Routing lives in `/apps/frontend/src/app` with route groups `(app)`, `(extension)`, `(provider)`.
- Always use SWR to fetch stuff, and use the "useFetch" hook from `/libraries/helpers/src/utils/custom.fetch.tsx`.

When using SWR, each one have to be in a separate hook and must comply with react-hooks/rules-of-hooks, never put eslint-disable-next-line on it.
When using SWR, each one has to be in a separate hook and must comply with react-hooks/rules-of-hooks, never put eslint-disable-next-line on it.

It means that this is valid:
const useCommunity = () => {
Expand All @@ -57,10 +40,42 @@ const useCommunity = () => {
};
}

- Linting of the project can run only from the root.
- Use only pnpm.
- Never use RAW SQL queries, always use Prisma.
- The system is in production with many users, if you want to change something, you need to be sure that you are not breaking anything for existing users and a migration might be needed
- Client state uses Zustand with two stores: the composer store (`components/new-launch/store.ts`) and the modal manager (`components/layout/new-modal.tsx`). The timezone preference is not Zustand - it is localStorage + dayjs (`components/layout/set.timezone.tsx`). There is no Redux.
- Styling is Tailwind 3 + SCSS tokens. Before writing any component look at:
- `/apps/frontend/src/app/colors.scss`
- `/apps/frontend/src/app/global.scss`
- `/apps/frontend/tailwind.config.cjs` (note: `.cjs`)

All the --color-custom* are deprecated, don't use them; use the `--new-*` tokens. The design language is documented in `DESIGN.md`.
`/apps/frontend/src/app/polonto.css` is vendored Polotno/Blueprint CSS, do not hand-edit it.

- Most UI is in `/apps/frontend/src/components`: `new-launch` (post composer), `launches` (planner/calendar), `layout` (app shell), `billing` (DOS shared billing), `agents` (CopilotKit chat), `media` (Polotno editor), `public-api`, `settings`, `auth`.
- `/apps/frontend/src/components/ui` is nearly empty. Shared form primitives live in `/libraries/react-shared-libraries/src/form`.
- Backend DTOs are reused in forms via `classValidatorResolver` (intentional coupling, keep it).

## Backend

When working on the backend we need to pass the 3 layers:
DTO >> Controller >> Service >> Repository (no shortcuts)
In some cases we will have
DTO >> Controller >> Manager >> Service >> Repository.

Most of the server logic lives in `/libraries/nestjs-libraries`.
The backend app is mostly used to write controllers and import from the libraries.

- Never use RAW SQL queries, always use Prisma (schema at `/libraries/nestjs-libraries/src/database/prisma/schema.prisma`).
- The database is PostgreSQL on Supabase with PgBouncer; the Prisma datasource uses `directUrl` for migrations.
- Publishing pipeline: `PostsService` starts a Temporal workflow (`postWorkflowV*`); workers run in `apps/orchestrator` with one activity worker per provider task queue.
- Code must always be generic: provider-specific logic only inside the provider file in `/libraries/nestjs-libraries/src/integrations/social`. Extend the provider interface and call it generically; never write `if (facebookProvider) {}` inside a generic file.

## Temporal rules (load-bearing)

- Workflow files that are already in origin/main can never be changed in place, because changing a workflow fails all its activities. Instead create a new workflow with the version, and everywhere the workflow is being called, change it to the new workflow version.
- Workflow activity parameters cannot be changed, as it will break the workflow. If we need to change the parameters, create a new activity with the new parameters, and then create a new workflow that uses the new activity.

## Working rules

- The system is in production with many users: make sure changes do not break anything for existing users, and a migration might be needed.
- Whenever you generate a PR, PR description, or similar, **always** follow the PR Template (.github/PULL_REQUEST_TEMPLATE.md)
- Every PR description **must** contain a `# QA` section with real, numbered steps a reviewer can follow to verify the change (setup, action, expected result), written so they can be run without asking the author anything. This is not optional and applies to humans and agents alike, including one-line fixes. The section is extracted verbatim and shown on the review board, so:
- Use the exact heading `# QA` (`# Testing`, `# Test plan`, `# How to test`, `# How to verify`, `# Verification`, `# Steps to test` and `# Manual testing` are also recognised, but prefer `# QA`). The whole heading must match, so something like `## Testing philosophy` is not picked up.
Expand All @@ -70,6 +85,6 @@ const useCommunity = () => {
- Avoid as much as possible creating new files with pure logic of algorithms, it's usually wrong
- When you write code, make sure that what you add looks like something similar somewhere else in the code, don't make weird patterns
- When you finished running, run another agents that matches the new code with the existing system code, to see that it looks similar and is not a weird pattern.
- Workflows files can never be changed if they are already in origin/main, because changing a workflow will fail all its activities, instead create a new workflow with the version, and everywhere the workflow being called, change it to the new workflow version.
- Workflows activities parameters cannot be changed, as it will break the workflow, if we need to change the parameters, if we need to change the parameters, we need to create a new activity with the new parameters, and then create a new workflow that uses the new activity.
- Code must always be generic, there can't be a way that a specific logic, let's say facebook or instagram, appear in a file that use a generic logic, instead, we need to edit the interface of the provider, add another function, and then generically call it from the generic code, and then implement the specific logic in the provider implementation. we can't have something like if(facebookProvider) {} inside a non facebook provider file.
- Linting of the project can run only from the root.
- Use only pnpm.
- Branding guard (`scripts/branding-guard.ts`, enforced in CI) blocks reintroducing upstream endpoints or branding; use `branding-guard-allow:` comments only for deliberate references.
2 changes: 2 additions & 0 deletions ROADMAP.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Crove Post Roadmap

> **Current batch (approved 2026-09-21):** the Minimal Batch - foundation safety (upstream sync, eslint 9 CI green, crove-sso leftovers, prod compose drift) and test/docs baseline (Playwright smoke, Vitest baseline, CLAUDE.md corrections, ADR-0001 + fork-delta inventory). Scope and deferrals: `docs/refactor/minimal-batch.md`. UI items below stay deferred until that batch is reviewed on beta.

## 1. Frontend & UI/UX Modernization (Crove OS Standards)

- [ ] **Design System & Visual Refresh**:
Expand Down
4 changes: 2 additions & 2 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ We consider an issue a vulnerability when it is a weakness in an in-scope, suppo

## Contacting Us

All security correspondence goes through [GAdvisory](https://postiz.gadvisory.org/request), our security advisory platform. The form routes four types of request:
All security reports and related correspondence must be submitted through [GAdvisory](https://postiz.gadvisory.org/request), our security advisory platform. The form routes four types of request:

- **Report a vulnerability.** See [Reporting Security Vulnerabilities](#reporting-security-vulnerabilities).
- **Dispute a CVE or Advisory.** Challenge the validity of a record we published. Disputes and their resolution are public and permanent. Our CVE Record Dispute Policy is linked from this flow.
Expand All @@ -64,7 +64,7 @@ If you discover a security vulnerability in the Postiz app, report it through [G
- Steps to reproduce the vulnerability
- Any relevant code or configuration files

If the report has immediate urgency, please also contact one (or more) of the maintainers via email:
Email the maintainers only when the report requires immediate, time-critical attention. Email does not replace submitting the report through GAdvisory.

- @egelhaus ([E-Mail](mailto:egelhaus@ennogelhaus.de))

Expand Down
Loading
Loading