docs: record Gate 0.8 resolution + Gate 0.9 LinkedIn app / CMA progress
- deferred-gates.md: Gate 0.8 RESOLVED — clean-room Postgres 17 + Redis 7 in a dedicated Dokploy project; service names, hosts, env-var locations recorded. - linkedin-apps.md: app created (Client ID 78s8f53y5spyo4), company-page + business-email verified, Community Management API Development Tier submitted (review in progress). Notes that other products grey out while CMA is pending. - docs/handoffs/2026-05-13-handoff.md: committed (was untracked). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+30
-8
@@ -4,15 +4,37 @@ Items that could not be completed in the Stage 0 execution window and must be re
|
||||
|
||||
## Gate 0.8 — Postgres + Redis on PaaS
|
||||
|
||||
**Status:** Deferred 2026-04-19.
|
||||
**Reason:** Dokploy MCP tools (`mcp__dokploy__*`) were not loaded in the Stage 0 session, and `DOKPLOY_API_KEY` was not in the WSL environment. Direct API query not possible in-session.
|
||||
**Blocks:** Stage 2 (database + API) — the scheduler and admin cannot run without a Postgres + Redis pair.
|
||||
**Resolution options:**
|
||||
1. **Recommended:** Restart Claude Code with the vault's `.mcp.json` Dokploy MCP attached; run `mcp__dokploy__list_applications` / equivalent against `sg-paas-s1.stargue.net` to verify or provision.
|
||||
2. Angelo confirms via Dokploy web UI and reports service names + connection hostnames.
|
||||
3. Provision fresh Postgres + Redis services in the `stargue-publishing-engine` Dokploy stack (clean room; isolates blast radius from other PaaS apps).
|
||||
**Status:** ✅ RESOLVED 2026-06-03 (via Dokploy MCP, resolution option 3 — clean-room stack).
|
||||
**Reason (historical):** Dokploy MCP tools (`mcp__dokploy__*`) were not loaded in the Stage 0 session, and `DOKPLOY_API_KEY` was not in the WSL environment. Direct API query not possible in-session.
|
||||
**Blocks (now cleared):** Stage 2 (database + API) — the scheduler and admin cannot run without a Postgres + Redis pair.
|
||||
|
||||
**Acceptance when resolved:** this file updated with service names, hostnames, and connection-string env-var locations (Dokploy secrets).
|
||||
### Resolution (2026-06-03)
|
||||
|
||||
Provisioned a dedicated clean-room Dokploy project on `sg-paas-s1.stargue.net`, isolating blast radius from other PaaS apps (option 3).
|
||||
|
||||
| Item | Value |
|
||||
|---|---|
|
||||
| Dokploy project | `stargue-publishing-engine` (`projectId: Y6R_4ML2N0Vsztk0UVi1W`) |
|
||||
| Environment | `production` (`environmentId: hkvob7vx02lzkn3GhpHMD`) |
|
||||
| Postgres service | "Publishing Engine Database" (`postgresId: O_BjqkxljdMU3xLb3q09M`) — image `postgres:17`, status `done` |
|
||||
| Postgres internal host | `stargue-pubeng-postgres-n9c1gc` (Docker network alias) port `5432` |
|
||||
| Postgres db / user | `publishing_engine` / `publishing_engine` |
|
||||
| Postgres volume | `stargue-pubeng-postgres-n9c1gc-data` → `/var/lib/postgresql/data` |
|
||||
| Redis service | "Publishing Engine Redis" (`redisId: fZR9Bdx8-3d99uOrrqFe5`) — image `redis:7`, status `done` |
|
||||
| Redis internal host | `stargue-pubeng-redis-9tebfd` (Docker network alias) port `6379` |
|
||||
| Redis volume | `stargue-pubeng-redis-9tebfd-data` → `/data` |
|
||||
|
||||
**Connection-string env-var locations (NOT stored in git):**
|
||||
- `DATABASE_URL` = `postgres://publishing_engine:<PG_PASSWORD>@stargue-pubeng-postgres-n9c1gc:5432/publishing_engine`
|
||||
- `REDIS_URL` = `redis://default:<REDIS_PASSWORD>@stargue-pubeng-redis-9tebfd:6379`
|
||||
- Secret **values** live in Dokploy (retrieve via `mcp__dokploy__postgres-one` / `mcp__dokploy__redis-one`). They will be injected as Dokploy secrets on the **app** services (`apps/mcp-linkedin`, `apps/scheduler`, `apps/admin`) once those are created in Stage 5+. No app service exists yet, so there is nowhere to attach them today.
|
||||
|
||||
**Remaining to fully unblock live DB tests:**
|
||||
1. Run `0000_initial_schema.sql` against the new DB. The internal hostname is only resolvable inside the Dokploy Docker network, so either (a) temporarily add an external port via `mcp__dokploy__postgres-saveExternalPort` and run `bun run db:migrate` from WSL with the external `DATABASE_URL`, then remove the port; or (b) run the migration from a one-shot container inside the stack.
|
||||
2. Run `bun run db:migrate:rehearse` (forward-then-rollback row-count hash check).
|
||||
3. Re-enable `INTEGRATION=1`-gated tests with the connection strings wired.
|
||||
|
||||
**Acceptance (met):** service names, hostnames, and connection-string env-var locations recorded above; secret values held in Dokploy, not committed.
|
||||
|
||||
## Gate 0.9 — LinkedIn Developer Portal apps
|
||||
|
||||
|
||||
Executable
+197
@@ -0,0 +1,197 @@
|
||||
---
|
||||
created: 2026-05-13T12:35
|
||||
updated: 2026-05-13T12:35
|
||||
tags:
|
||||
---
|
||||
|
||||
# Publishing Engine — Session Handoff 2026-05-13
|
||||
|
||||
**Purpose:** let the next session pick up cold with full state of the Stargue Publishing Engine build. Source: this vault note + mirror at `docs/handoffs/2026-05-13-handoff.md` in the repo.
|
||||
|
||||
**Repo:** `https://git.stargue.net/admin/stargue-publishing-engine` (local: `/home/devuser/projects/stargue-publishing-engine/` via WSL Debian)
|
||||
**Plan v2 (SSoT):** [[Plan - Phase 1 Automated Publishing Engine|Plan - Phase 1 Automated Publishing Engine.md]] (vault) + `docs/plans/2026-04-19-phase1-plan.md` (repo mirror)
|
||||
**PRD:** [[Publishing Engine PRD]]
|
||||
**Panel verdicts:** `docs/plans/bmad-panel-verdicts-publishing-engine-phase1-20260419.json` (1 APPROVE, 6 REVISE, 0 REJECT — all principles ≥3)
|
||||
**Doctrine:** `.clinerules/12-foundational-principles.md` adopted from DQMS
|
||||
|
||||
---
|
||||
|
||||
## Where we stand — quick read
|
||||
|
||||
| Stage | Status | Commit | Tests | Notes |
|
||||
|---|---|---|---|---|
|
||||
| 0 — Governance + scaffolding | ✅ Complete | `1dc1a1a` (2026-04-19) | n/a | 11 workspaces typecheck clean |
|
||||
| 1 — Shared packages | ✅ Complete | `e529651` (2026-04-26) | 50/50 | 4 packages: schema, sanitize, linkedin-client (stubs), observability |
|
||||
| 2 — DB + middleware + API | 🟡 Partial | `c73b7e4` (2026-04-26) | 79/79 cumulative | Live-DB integration tests blocked by **gate 0.8** |
|
||||
| 3 — LinkedIn MCP server | 🟡 Partial | `7aa3137` (2026-04-26) | 106/106 cumulative | Live-LinkedIn blocked by **gate 0.9** |
|
||||
| 4 — Scheduler + cadence | 🟡 Partial | `a4e4306` (2026-04-26) | 117/117 cumulative | BullMQ + integration blocked by **gates 0.8 + 0.9** |
|
||||
| 5 — Admin dashboard (Next.js + A11y) | ❌ Not started | — | — | Independent of gates; can start anytime |
|
||||
| 6 — stargue-com/.net integration | ❌ Not started | — | — | Independent of gates |
|
||||
| 7 — Content + metrics bootstrap | ❌ Not started | — | — | 7.1 + 7.2 independent of gates |
|
||||
|
||||
**Last activity:** 2026-04-26 (commit `a4e4306`). Repo idle since. Today is 2026-05-13 — ~2.5 weeks of pause.
|
||||
|
||||
---
|
||||
|
||||
## Deferred gates (the real blockers)
|
||||
|
||||
### Gate 0.8 — Postgres + Redis on PaaS
|
||||
|
||||
**Status:** Dokploy MCP was loaded in the 2026-04-19 session but verification not completed before pause. **Resume action:** with Dokploy MCP attached, run `mcp__dokploy__project-all` → identify Stargue PaaS project → `mcp__dokploy__postgres-search` + `mcp__dokploy__redis-search` to see existing instances; provision new ones in a `stargue-publishing-engine` project if none are shareable.
|
||||
|
||||
**Why it blocks:** Stage 2 live-DB integration tests, Stage 3 token-store live tests, Stage 4 BullMQ worker, Stage 5 admin auth flow.
|
||||
|
||||
**Next steps when resolved:**
|
||||
1. Run `0000_initial_schema.sql` migration on the new DB
|
||||
2. Run `bun run db:migrate:rehearse` (script lives at `packages/schema/db/migrations/rehearse.ts`)
|
||||
3. Wire connection strings into Dokploy secrets `DATABASE_URL`, `REDIS_URL`
|
||||
4. Re-enable the integration tests gated behind `INTEGRATION=1`
|
||||
|
||||
### Gate 0.9 — LinkedIn Developer Portal apps
|
||||
|
||||
**Status:** Pending Angelo's manual action. Checklist ready at `docs/linkedin-apps.md`.
|
||||
|
||||
**Why it blocks:** Stage 3.1–3.7 live posting, Stage 4 end-to-end publish, Stage 7.4 first scheduled post.
|
||||
|
||||
**Next steps when resolved:**
|
||||
1. Angelo registers app at linkedin.com/developers/ linked to Stargue Company Page `urn:li:organization:2605890`
|
||||
2. Enables Sign-In with OpenID Connect + Share on LinkedIn (instant self-service)
|
||||
3. Submits Community Management API + MDP partner-access requests (multi-week review — file ASAP to start the clock)
|
||||
4. Drops `LINKEDIN_CLIENT_ID`, `LINKEDIN_CLIENT_SECRET`, `LINKEDIN_TOKEN_ENCRYPTION_KEY` into Dokploy secrets
|
||||
5. Update `docs/linkedin-apps.md` registry with app IDs
|
||||
|
||||
---
|
||||
|
||||
## What's already built (don't re-invent)
|
||||
|
||||
### `packages/schema` (full SSoT for data shapes)
|
||||
- `frontmatter.ts` — Zod schema for vault frontmatter (status, language, outlets[], sanitize, scheduled, version)
|
||||
- `db.ts` — Drizzle schema for 7 tables: content, publications (with `idempotency_key UNIQUE`), approvals, metrics, linkedin_tokens, audit, outlet_feature_flags
|
||||
- `rate-limit.ts` — token-bucket implementation, pure-function
|
||||
- `csrf.ts` — double-submit cookie pattern
|
||||
- `authz.ts` — Cerbos-equivalent policy primitives
|
||||
- `api-contracts.ts` — Zod request/response schemas for admin API
|
||||
- `drizzle.config.ts` + `db/migrations/0000_initial_schema.sql` + `0000_initial_schema.down.sql` + `db/migrations/rehearse.ts`
|
||||
|
||||
### `packages/sanitize` (fail-closed content pipeline)
|
||||
- `rules.ts` — PRIVATE_PATH_PREFIXES (Family Matters, Financial Matters, Journal, Clients NDA…), PRIVATE_PATH_PATTERNS, PRIVATE_TAGS (`#private`, `#heal-internal`, `#confidential`), OUTLET_LENGTH_LIMITS
|
||||
- `errors.ts` — SanitizeError with codes: PRIVATE_PATH_BLOCKED, PRIVATE_TAG_BLOCKED, WIKILINK_TO_PRIVATE_PATH, OUTLET_LENGTH_EXCEEDED
|
||||
- `index.ts` — `sanitize(markdown, opts)` returns `{ body, contentHash, warnings }` — strips wikilinks/embeds/dataview/callouts, enforces blocklist + tag firewall + length, computes SHA-256 hash
|
||||
- `corpus.test.ts` — Stage 1.2 DoD test: 12 private + 6 clean fixtures round-trip correctly
|
||||
|
||||
### `packages/linkedin-client` (Posts API client + token store)
|
||||
- `types.ts` — LinkedIn Posts API request/response types (Posts API v202404, not legacy UGC)
|
||||
- `client.ts` — HTTP client; respects `LinkedIn-Version: 202404` + `X-Restli-Protocol-Version: 2.0.0`
|
||||
- `token-store.ts` — encrypted persistence; **uses AES-256-GCM via `node:crypto`** (NOT libsodium — see D-001 in `docs/deferred-gates.md` for the deviation rationale: libsodium-wrappers ESM bug under Bun)
|
||||
- `client.test.ts` + `token-store.test.ts` — 4/4 round-trip tests pass
|
||||
|
||||
### `packages/observability` (Pino + correlation IDs)
|
||||
- `index.ts` — Pino logger with PII-redaction paths (access_token, refresh_token, client_secret, *_ct fields), `newCorrelationId()`, `child(bindings)` helper
|
||||
|
||||
### `apps/mcp-linkedin` (Stage 3 partial — structural complete, live blocked)
|
||||
- `server.ts` — `createServer` factory pattern, injectable deps (KillSwitch, AdvisoryLock); MCP_SPEC_VERSION pinned `2024-11-05`; `validateToolCall`, `listTools`, `outletForAuthorUrn` helpers
|
||||
- `tools.ts` — 9 Zod tool schemas: whoami, auth_status, create_post, create_article, upload_media, create_post_with_media, delete_post, get_post_metrics, get_profile_stats
|
||||
- `oauth.ts` — auth-code URL builder + HMAC-protected state parameter (no PKCE — LinkedIn 3LO doesn't support it)
|
||||
- `kill-switch.ts` — `outlet_feature_flags` reader with cache invalidation
|
||||
- `refresh-lock.ts` — Postgres advisory-lock primitive; **4-concurrent rotation test passes** (TEA gap 3 closed)
|
||||
|
||||
### `apps/scheduler` (Stage 4 partial — pure pieces complete)
|
||||
- `cadence.ts` — Beta(1,19) posterior optimizer, `propose(history, config) → [Proposal]`; all 4 thresholds verified (≥8 samples, ≥4 weeks, ≥20% ratio, disjoint 95% CIs); never auto-applies (RBR)
|
||||
- `publish-loop.ts` — state-machine transition function `pending→queued→dispatching→published`, retry-vs-DLQ branch, cancellation path
|
||||
- `worker.ts` — entry stub (BullMQ wiring blocked by Redis on gate 0.8)
|
||||
|
||||
### `apps/admin` (not started)
|
||||
- `src/index.ts` — stub only. Next.js scaffold + Authentik SSO + queue/publications/auth/metrics pages all pending.
|
||||
|
||||
---
|
||||
|
||||
## Architecture decisions worth remembering
|
||||
|
||||
1. **D-001 token cipher: AES-256-GCM, not libsodium secretbox.** Bun ESM bug in `libsodium-wrappers`. Same AEAD security profile. Documented in `docs/deferred-gates.md`. Remediation path noted if libsodium fixes the bug.
|
||||
2. **Scheduler imports `linkedin-client` directly** — MCP transport is stdio-only for interactive Claude Code use. No HTTP MCP transport in Phase 1 (architect gap 2).
|
||||
3. **`apps/api` collapsed into `apps/admin`** — Next.js App Router route handlers cover the API surface; less infra (architect gap 1).
|
||||
4. **LinkedIn Posts API `/rest/posts`** — NOT the legacy `/v2/ugcPosts`. Headers: `LinkedIn-Version: 202404`, `X-Restli-Protocol-Version: 2.0.0`.
|
||||
5. **No PKCE in OAuth** — LinkedIn 3LO doesn't document it; confidential-client with HMAC `state` parameter is what we use.
|
||||
6. **`idempotency_key UNIQUE` on `publications`** — sha256(content_id || outlet || scheduled_at). Prevents double-post on retry.
|
||||
7. **Kill-switch via `outlet_feature_flags` table** — fast disable without redeploy. Cached at MCP server with invalidation on table change.
|
||||
|
||||
---
|
||||
|
||||
## Next session — priority order
|
||||
|
||||
### Path A: Resolve gates first (recommended if Angelo + Dokploy access available)
|
||||
1. **Gate 0.8** — Dokploy MCP query → provision Postgres + Redis in `stargue-publishing-engine` project on `sg-paas-s1.stargue.net`
|
||||
2. **Gate 0.9** — Angelo files LinkedIn Dev Portal apps (~30 min for OIDC + Share; submit Community Management API + MDP requests to start the partner-approval clock)
|
||||
3. With both gates open, unblock Stages 2.6, 3.4–3.9, 4.1–4.3 live integration tests
|
||||
4. Move to Stage 5 (admin dashboard)
|
||||
|
||||
### Path B: Continue parallel work (if gates remain blocked)
|
||||
1. **Stage 5** — Admin dashboard scaffold: Next.js App Router + shadcn/ui + Nine Laws design tokens; pages `/queue`, `/publications/:id`, `/auth/linkedin`, `/metrics`; A11y CI (axe-core + @axe-core/playwright). Authentik stub for local dev.
|
||||
2. **Stage 6** — Add `@stargue/sanitize` + `@stargue/schema` as workspace deps to stargue-com + stargue-net; replace ad-hoc frontmatter parsing; assert zero wikilinks in rendered HTML.
|
||||
3. **Stage 7.1** — Run `/market audit` baseline on stargue.com + stargue.net; save to `docs/marketing-baseline-2026-05.json`.
|
||||
4. **Stage 7.2** — Draft 7 Cs posts 2–8 (Commitment, Co-Creation, Connection, Communication, Celebration & Course Correction, Caring & Crossing, Synthesis) — long-form for stargue.com + LinkedIn-optimized variants. Source content from `7 Cs LinkedIn Series - Continuation Plan.md`. Run each through autoresearch optimization to composite ≥8.
|
||||
|
||||
### Path C: Mixed (most realistic)
|
||||
- Angelo does Gate 0.9 in parallel (~30 min self-service; partner approvals run async for weeks)
|
||||
- Claude provisions Gate 0.8 via Dokploy MCP
|
||||
- Concurrently start Stage 5 and 7.2
|
||||
|
||||
---
|
||||
|
||||
## Open items / things to verify
|
||||
|
||||
1. **MDP + Community Management API timeline** — once filed, track approval state weekly. MDP rejection is the trigger for the 60-day-re-auth fallback.
|
||||
2. **Authentik instance reachability** — plan §8 q3 said "shared instance for all Stargue services"; needs runtime verification before Stage 5.2.
|
||||
3. **Neon free-tier mirror** — Stage 7.5 DR test pending. Set up nightly `pg_dump → Neon` cron when gate 0.8 resolved.
|
||||
4. **stargue-com/.net package.json sync** — collision was fixed (commit `fd43214` on stargue-net) — verify both repos still align before Stage 6.
|
||||
5. **LinkedIn algorithm-reach risk** — plan §9 row added by analyst panel. Once first 4 posts ship, monitor engagement-delta vs Angelo's existing manual baseline; if suppression detected, fall back to draft-and-prompt workflow.
|
||||
|
||||
---
|
||||
|
||||
## Files to read first in next session
|
||||
|
||||
In order, for cold start:
|
||||
1. This handoff
|
||||
2. `docs/plans/2026-04-19-phase1-plan.md` (in the repo) — full plan v2
|
||||
3. `docs/deferred-gates.md` — for D-001 + gate status
|
||||
4. `CLAUDE.md` in the repo — for governance + canonical LinkedIn facts
|
||||
5. Last 4 commits via `git log` — for exact stage progress
|
||||
6. `docs/linkedin-apps.md` — for Angelo's manual checklist
|
||||
|
||||
---
|
||||
|
||||
## Memory notes already saved
|
||||
|
||||
- `project_publishing_engine.md` — overall project state
|
||||
- D-001 cipher deviation is in `docs/deferred-gates.md` (in repo) — no separate memory note needed since the deviation is project-local
|
||||
- BMAD panel verdicts cached at `docs/plans/bmad-panel-verdicts-publishing-engine-phase1-20260419.json`
|
||||
|
||||
---
|
||||
|
||||
## Commands cheatsheet
|
||||
|
||||
```bash
|
||||
# WSL Debian — always run there
|
||||
wsl -d Debian -- bash -c 'cd /home/devuser/projects/stargue-publishing-engine && <cmd>'
|
||||
|
||||
bun install # workspace deps
|
||||
bun run typecheck # all 11 workspaces
|
||||
bun run test # 117/117 currently passing
|
||||
bun run db:migrate # apply Drizzle migrations (needs DATABASE_URL)
|
||||
bun run db:migrate:rehearse # expand-then-contract rehearsal
|
||||
|
||||
# Gitea
|
||||
git push # auto-deploys via Dokploy webhook (Phase 0 sites);
|
||||
# Publishing Engine apps deploy on separate Dokploy stack (Stage 5+)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Related
|
||||
|
||||
- [[Publishing Engine PRD]]
|
||||
- [[Plan - Phase 1 Automated Publishing Engine]]
|
||||
- [[7 Cs LinkedIn Series - Continuation Plan]]
|
||||
- [[Design Philosophy - The Nine Laws of the Hearth]]
|
||||
- [[Outlet Profiles/LinkedIn]]
|
||||
- [[Implementation Progress]] — update with this handoff's status table after the next session
|
||||
+73
-25
@@ -2,45 +2,93 @@
|
||||
|
||||
**Status tracker for Stargue's LinkedIn apps.** Every row must stay current — Claude Code verifies against this file during Stage 0 DoD 0.9.
|
||||
|
||||
## Applications
|
||||
## App: Stargue Publishing Engine (created 2026-06-03)
|
||||
|
||||
| App | Product | Purpose | Scopes granted | State | App ID | Approval date | Notes |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| Stargue Publishing Engine — Sign In | Sign In with LinkedIn using OpenID Connect | Identity / `whoami` | `openid profile email` | **TODO: register** | — | — | Standard — no approval required beyond Dev Portal self-service |
|
||||
| Stargue Publishing Engine — Member Share | Share on LinkedIn | Personal-profile posts (Angelo) | `w_member_social` | **TODO: register** | — | — | Standard — attached to the same app as Sign In |
|
||||
| Stargue Publishing Engine — Org Share | Community Management API | Company-page posts (`urn:li:organization:2605890`) | `w_organization_social`, `r_organization_social` | **TODO: apply** | — | — | Requires LinkedIn partner approval; submit via Dev Portal "Request access" |
|
||||
| Stargue Publishing Engine — Refresh | Marketing Developer Platform (MDP) | Programmatic refresh tokens (eliminates 60-day re-auth) | (extends above) | **TODO: apply** | — | — | Requires LinkedIn partner approval; multi-week review |
|
||||
- **Client ID:** `78s8f53y5spyo4`
|
||||
- **Client Secret:** present on Auth tab (Primary Client Secret) — copy to Dokploy secret `LINKEDIN_CLIENT_SECRET`, never commit
|
||||
- **App type:** Standalone app
|
||||
- **LinkedIn Page:** Stargue (`urn:li:organization:2605890`) — association is permanent, **NOT yet verified** (see below)
|
||||
- **Privacy policy URL:** https://stargue.com/privacy (live 2026-06-03) ✅
|
||||
- **Business email:** `info@stargue.com` — **verified 2026-06-03** ✅ (required for CMA)
|
||||
- **Access-token TTL:** 2 months / 5,184,000 s (confirms the 60-day re-auth design; programmatic refresh is MDP-gated)
|
||||
- **Authorized redirect URLs:** none added yet
|
||||
- **OAuth scopes:** none yet
|
||||
|
||||
## Status update — 2026-06-03 13:15
|
||||
|
||||
**Community Management API (Development Tier) = SUBMITTED → "Review in progress."** Access form completed (legal name `Stargue N.V.`, Curaçao address Dwarsweg 9 Julianadorp LP71, website stargue.com, 3 use cases: Page management + Page analytics + Profile management, first-party compliance description). Decision comes by email to `info@stargue.com`. (Note: the Qualtrics "session expired" end-screen was a false alarm — it did submit.)
|
||||
|
||||
**⚠️ NEW OBSERVATION — once CMA was requested, ALL other products greyed out** (Share on LinkedIn, Sign In with OpenID Connect, etc. now show disabled "Request access"). **Uncertain (not yet confirmed) whether this is:**
|
||||
- (a) **temporary** — a lock while CMA is in review, that lifts on approval; or
|
||||
- (b) **permanent** — CMA apps are meant to be CMA-only (consistent with FAQ #1/#2 treating CMA + other products as a separate-app pattern).
|
||||
|
||||
**Architecture decision deferred pending CMA outcome:**
|
||||
- If other products **un-grey** after CMA approval → keep single app, add Sign In + Share here.
|
||||
- If they **stay greyed** → **two-app split** after all: this app = CMA (company + profile posting via CMA), a **second app** = Sign In (OIDC identity) + Share on LinkedIn (`w_member_social`).
|
||||
- **Possible simplification:** CMA's *Profile management* use case may already cover posting to Angelo's own profile, reducing/eliminating the need for a separate "Share on LinkedIn" product. Confirm when wiring OAuth scopes.
|
||||
|
||||
## ⚠️ Why the Community Management API is greyed — VERIFIED (2026-06-03)
|
||||
|
||||
The app has **no other products**, so FAQ #4 ("greyed because the app already has other products") is **not** the cause here. The real prerequisites — confirmed against LinkedIn docs and visible on the app's **Settings** tab — are:
|
||||
|
||||
1. **Company-Page verification (PRIMARY GATE).** Settings shows *"This app is not verified as being associated with this company"* + a **Verify** button. A **super-admin of the Stargue Company Page** must approve the app↔page association. CMA stays greyed until done. **Dependency: Angelo must be, or have access to, a super-admin of the Stargue Page.**
|
||||
2. **Business-email verification.** Settings banner: *"Update your business email…"*. The CMA access form requires a **verified business email**.
|
||||
3. **Access-form requirements.** CMA is for **registered legal organizations, commercial use only**. Form asks for: legal org name, registered address (Curaçao), website, **privacy policy URL** (✅ live), verified business email.
|
||||
4. **Secondary — product order (FAQ #4).** If an app *already has* other products, the CMA request greys out. Not our cause today (clean app), but it means: **request CMA before adding Share/Sign In**, or keep CMA on its own app.
|
||||
|
||||
### Corrected recommendation: single app, CMA-first
|
||||
|
||||
1. **Verify** the app ↔ Stargue Page (super-admin approves).
|
||||
2. **Set + verify** the business email.
|
||||
3. Request **Community Management API first** → complete access form → **Development Tier** (limits: 500 req/app, 100 req/member).
|
||||
4. Apply **Standard Tier** (access form + screencast demonstrating each use case).
|
||||
5. **Then** add **Share on LinkedIn** + **Sign In with OpenID Connect** (instant) for personal posting + identity.
|
||||
|
||||
(Two-app split — CMA on its own app, Share/Sign In on another — remains a fallback if Page verification cannot be completed on this app.)
|
||||
|
||||
## Products — observed state (2026-06-03 Products tab)
|
||||
|
||||
| Product | Needed for | Self-service? | State on this app |
|
||||
|---|---|---|---|
|
||||
| Community Management API | Company-page posts (`w_organization_social`, `r_organization_social`) | No — needs verification + Dev→Standard | **🔒 Greyed** — pending Page verification + business email |
|
||||
| Sign In with OpenID Connect | Identity / `whoami` (`openid profile email`) | Yes (instant) | Available — request AFTER CMA |
|
||||
| Share on LinkedIn | Personal-profile posts (`w_member_social`) | Yes (instant) | Available — request AFTER CMA |
|
||||
| Marketing Developer Platform / Advertising / Lead / Conversions | Programmatic refresh tokens; marketing | No (partner review) | Greyed; optional (60-day re-auth fallback exists) |
|
||||
|
||||
Other products present but not needed: LinkedIn Ad Library, Verified on LinkedIn (available); Live Events, Events Mgmt, Member/Pages Data Portability (greyed).
|
||||
|
||||
## OAuth redirect URIs
|
||||
|
||||
- Production: `https://publishing.stargue.net/auth/linkedin/callback`
|
||||
Add under the app's **Auth** tab (not yet done):
|
||||
- Production: `https://publishing.stargue.net/auth/linkedin/callback` (note: `publishing.stargue.net` subdomain is Stage 5+; admin app not built yet)
|
||||
- Local dev: `http://localhost:3002/auth/linkedin/callback`
|
||||
|
||||
## Client credentials
|
||||
|
||||
Stored in Dokploy secrets on `sg-paas-s1.stargue.net`:
|
||||
- `LINKEDIN_CLIENT_ID`
|
||||
- `LINKEDIN_CLIENT_SECRET`
|
||||
- `LINKEDIN_TOKEN_ENCRYPTION_KEY` (32-byte key for `crypto_secretbox`)
|
||||
Dokploy secrets on `sg-paas-s1.stargue.net` (project `stargue-publishing-engine`, once app services exist in Stage 5+):
|
||||
- `LINKEDIN_CLIENT_ID` = `78s8f53y5spyo4`
|
||||
- `LINKEDIN_CLIENT_SECRET` = (from Auth tab — pending copy)
|
||||
- `LINKEDIN_TOKEN_ENCRYPTION_KEY` (32-byte; **AES-256-GCM** per D-001 — see `deferred-gates.md`)
|
||||
|
||||
## Manual setup checklist (Stage 0.9)
|
||||
|
||||
1. Sign in to `https://www.linkedin.com/developers/` as Angelo (personal account).
|
||||
2. Create app "Stargue Publishing Engine" linked to Stargue Company Page `urn:li:organization:2605890` (required for Community Management API eligibility).
|
||||
3. Under **Products**, request:
|
||||
- Sign In with LinkedIn using OpenID Connect (self-service; instant)
|
||||
- Share on LinkedIn (self-service; instant)
|
||||
- Community Management API (submit partner-access request — fill in use-case: "Programmatic posting of original content to Stargue Company Page for knowledge-management-as-a-service practice")
|
||||
- Marketing Developer Platform (separate partner-access request — fill in use-case: "Automate posting and engagement-metric collection for owned content from a self-hosted publishing pipeline")
|
||||
4. Under **Auth**, add redirect URIs above.
|
||||
5. Copy Client ID and Client Secret to Dokploy secrets (never commit).
|
||||
6. Update this file with the app ID.
|
||||
7. Re-request Community Management API + MDP if denied initially, with more detailed use-case.
|
||||
1. ✅ Sign in to `https://www.linkedin.com/developers/` as Angelo.
|
||||
2. ✅ Create app "Stargue Publishing Engine" linked to Page `urn:li:organization:2605890` (Client ID `78s8f53y5spyo4`).
|
||||
3. ✅ Privacy policy URL live at https://stargue.com/privacy.
|
||||
4. ✅ **Verify app ↔ Company Page** (done 2026-06-03 — un-greyed all products). PRIMARY gate for CMA.
|
||||
5. ✅ **Business email verified** — `info@stargue.com` (2026-06-03).
|
||||
6. ☐ **← NEXT:** Request **Community Management API FIRST**: add product → complete access form (legal name Stargue Inc., Curaçao address, website, privacy URL, business email `info@stargue.com`) → Dev Tier → apply Standard Tier later (screencast).
|
||||
7. ☐ THEN request **Sign In + Share on LinkedIn** (instant).
|
||||
8. ☐ **Auth tab:** add redirect URIs above.
|
||||
9. ☐ Copy **Client Secret** → Dokploy secret `LINKEDIN_CLIENT_SECRET` (never commit).
|
||||
10. ☐ Keep this file current with app IDs + states.
|
||||
|
||||
## References
|
||||
|
||||
- [LinkedIn Developer Portal](https://www.linkedin.com/developers/)
|
||||
- [Community Management — Overview + FAQ (Microsoft Learn)](https://learn.microsoft.com/en-us/linkedin/marketing/community-management/community-management-overview)
|
||||
- [Organizations & Brands Overview (Microsoft Learn)](https://learn.microsoft.com/en-us/linkedin/marketing/community-management/organizations)
|
||||
- [Increasing Access — tiers & app review](https://learn.microsoft.com/en-us/linkedin/marketing/increasing-access)
|
||||
- [Quick Start — Apply for API Access](https://learn.microsoft.com/en-us/linkedin/marketing/quick-start)
|
||||
- [Posts API](https://learn.microsoft.com/en-us/linkedin/marketing/community-management/shares/posts-api)
|
||||
- [3-Legged OAuth Flow](https://learn.microsoft.com/en-us/linkedin/shared/authentication/authorization-code-flow)
|
||||
- [Programmatic Refresh Tokens](https://learn.microsoft.com/en-us/linkedin/shared/authentication/programmatic-refresh-tokens)
|
||||
- [Community Management API overview](https://learn.microsoft.com/en-us/linkedin/marketing/community-management/)
|
||||
|
||||
Reference in New Issue
Block a user