Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
487963d
Add private partner catalog and article relevance evaluation
abhi1693 Oct 2, 2026
1ffda5d
Automate launch platform partnerships and standardize admin management
abhi1693 Oct 2, 2026
880d617
Fix partner sync recovery and superseded evaluations
abhi1693 Oct 2, 2026
3659df4
Consolidate partnership schema into one migration
abhi1693 Oct 2, 2026
46743eb
Escape browser fixture request values in failure logs
abhi1693 Oct 3, 2026
13e6b11
Cover partner collection budgets and correct literal search
abhi1693 Oct 3, 2026
bf17fbc
Add partner portal with memberships and performance analytics
abhi1693 Oct 7, 2026
079c772
Track partner impressions and clicks across reader clients
abhi1693 Oct 7, 2026
811a786
Fix partner API Docker workspace manifests
abhi1693 Oct 8, 2026
b7032f7
Align partner sign-in with shared DevFeed login
abhi1693 Oct 8, 2026
a687558
Use admin workspace design for partner portal
abhi1693 Oct 8, 2026
2645a5c
Separate partner reporting pages from admin management
abhi1693 Oct 8, 2026
6884299
Require partner role for portal authentication
abhi1693 Oct 8, 2026
5181471
Use common admin pages and controls for partnerships
abhi1693 Oct 8, 2026
bc033eb
Define partnership tiers, benefits and member user selection
abhi1693 Oct 8, 2026
a08ce35
Register partner identities for account member selection
abhi1693 Oct 8, 2026
1e5ded9
Separate partner overview from performance reporting
abhi1693 Oct 8, 2026
042527d
Add partner navbar account dropdown
abhi1693 Oct 8, 2026
4a77881
Use account paths for partner portal pages
abhi1693 Oct 8, 2026
63a8df2
Remove legacy partner portal URLs
abhi1693 Oct 8, 2026
39c68bd
Remove redundant partner portal labels
abhi1693 Oct 8, 2026
f1ada3a
Select partner asset products from catalog dropdown
abhi1693 Oct 8, 2026
589cd2b
Show partner member names and emails in admin
abhi1693 Oct 8, 2026
c409158
Link partner accounts from admin user details
abhi1693 Oct 8, 2026
ffc328b
Associate partner connections with a single account
abhi1693 Oct 8, 2026
5b440f6
Show only approved products in asset selector
abhi1693 Oct 8, 2026
30035c4
Remove partner connection form helper text
abhi1693 Oct 8, 2026
3be55e2
Name linked partner accounts in connection details
abhi1693 Oct 8, 2026
93818f6
Configure partner API connectors from saved definitions
abhi1693 Oct 8, 2026
2d0de48
Show partner connector field errors and require dropdown choices
abhi1693 Oct 8, 2026
712eaf1
Preview raw partner API responses beside connector settings
abhi1693 Oct 8, 2026
a1fccc3
Highlight partner field mappings in API response previews
abhi1693 Oct 8, 2026
cf2b3df
Fix partner image probes and scope job kind compatibility exceptions
abhi1693 Oct 8, 2026
3333ff9
Collect partner coverage and fix quality gate findings
abhi1693 Oct 9, 2026
8c04612
Preserve partner schema and tests after updating master
abhi1693 Oct 9, 2026
e091f23
Run portal browser fixtures with their workspace Next binary
abhi1693 Oct 9, 2026
1c0b488
Preserve partner database cleanup with the typed FastAPI dependency
abhi1693 Oct 10, 2026
0d03d63
Synchronize browser focus before partner-branch reader checks
abhi1693 Oct 10, 2026
24808dc
Merge master into partnership branch
abhi1693 Oct 11, 2026
9463cbb
Automate partner promotions with contextual campaigns
abhi1693 Oct 11, 2026
0199218
Generate disposable signing keys in promotion tests
abhi1693 Oct 11, 2026
c454923
Add sorting to partner product performance
abhi1693 Oct 11, 2026
566ff33
Complete contextual partner product placements
abhi1693 Oct 11, 2026
5f9908f
Add advanced audience targeting for Platinum and Diamond
abhi1693 Oct 11, 2026
580964d
Add native ad formats and per-product placement controls
abhi1693 Oct 11, 2026
904e920
Keep sponsored products available across feed refreshes
abhi1693 Oct 11, 2026
a7a8642
Highlight sponsored cards with an amber hover border
abhi1693 Oct 12, 2026
273f42b
Filter ineligible placements before acquiring attribution locks
abhi1693 Oct 12, 2026
6a04dda
Bound automatic promotion enrollment for large catalogs
abhi1693 Oct 12, 2026
bba0273
Protect public partner quotas from caller abuse and replay
abhi1693 Oct 12, 2026
41ec2e1
Preserve contextual matches across unchanged catalog imports
abhi1693 Oct 12, 2026
c77dd2f
Remove grandfathered partner campaign exemptions
abhi1693 Oct 12, 2026
922d46d
Expire mounted partner placements without shifting the feed
abhi1693 Oct 12, 2026
e30e90d
Authorize partner account URLs independently of picker pages
abhi1693 Oct 12, 2026
a06b579
Bound partner gateway request body reads
abhi1693 Oct 12, 2026
4d86117
Bound partner tracking deduplication retention
abhi1693 Oct 12, 2026
9856d88
Scope placement history lookups to eligible products
abhi1693 Oct 12, 2026
6e0c243
Queue targeted partner match invalidation
abhi1693 Oct 12, 2026
c5590e7
Aggregate statistics for paginated partner connections
abhi1693 Oct 12, 2026
764fe52
Share admin and partner UI primitives
abhi1693 Oct 12, 2026
2689fc9
Remove unused placement view history
abhi1693 Oct 12, 2026
60b288e
Consolidate partner preference requests and contracts
abhi1693 Oct 12, 2026
ea21631
Consolidate partnership migrations into one revision
abhi1693 Oct 12, 2026
89aad00
Fix partnership CI checks and merge current master
abhi1693 Oct 12, 2026
8276ba9
Fix CI fixtures and stabilize performance measurements
abhi1693 Oct 13, 2026
886b415
Resolve partnership quality gate findings
abhi1693 Oct 13, 2026
124e536
Make campaign cap regression independent of UTC time
abhi1693 Oct 13, 2026
c48e88f
Compare API performance on matched runners
abhi1693 Oct 13, 2026
dc90219
Constrain benchmark report paths and stream seed statistics
abhi1693 Oct 13, 2026
6a365ed
Create benchmark statistics with owner-only permissions
abhi1693 Oct 13, 2026
fd97876
Prioritize grounded tasks in native ad delivery
abhi1693 Oct 13, 2026
b2c9244
Keep native placements unobtrusive and restore organic results
abhi1693 Oct 13, 2026
ebba43f
Add confirmed product placement controls and exact previews
abhi1693 Oct 13, 2026
6c06a49
Merge branch 'master' into feat/partnership
abhi1693 Oct 13, 2026
a9765d9
Unify the partner workspace and add import management
abhi1693 Oct 13, 2026
6ca067e
Tighten partner portal layouts and dashboard density
abhi1693 Oct 13, 2026
80060a5
Compare impressions and clicks on partner delivery charts
abhi1693 Oct 13, 2026
dd44a63
Use shared controls throughout the partner portal
abhi1693 Oct 13, 2026
4a2825b
Share connection editors and add secure partner API previews
abhi1693 Oct 13, 2026
7ee116a
Keep connector mapping indicators inside inputs
abhi1693 Oct 13, 2026
b919483
Add custom product ad images with URL and file uploads
abhi1693 Oct 13, 2026
ad86838
Allow partners to advertise products without import connections
abhi1693 Oct 13, 2026
68f50c2
Keep archived partner products discoverable
abhi1693 Oct 13, 2026
e45ed1f
Put account filtering in the products table header
abhi1693 Oct 13, 2026
4fa3181
Split partner account settings into focused sections
abhi1693 Oct 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
35 changes: 34 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,8 @@ DEVFEED_FARO_ENABLED=false
DEVFEED_AI_QUOTA_PACING_ENABLED=false
DEVFEED_AI_QUOTA_RESERVE_PERCENT=20

# Image storage: credentials stay in the worker and user API; reader APIs use the public URL.
# Image storage: credentials stay in the images worker and private APIs for avatar/ad uploads.
# Public reader APIs and frontends use only the public URL.
# Enable the `images` Compose profile for imgproxy and the dedicated Images worker.
# Topic logos require public GET/HEAD CORS for card exports; see apps/aggregator/TOPIC_LOGOS.md.
DEVFEED_IMAGE_STORAGE_ENABLED=false
Expand Down Expand Up @@ -270,3 +271,35 @@ DEVFEED_ARTICLE_TOPIC_PROPOSALS_ENABLED=true
# DEVFEED_MCP_ACCESS_TOKEN_TTL_SECONDS=900
# DEVFEED_USER_MCP_SESSION_TTL_SECONDS=2592000
# DEVFEED_USER_MCP_SESSION_ABSOLUTE_TTL_SECONDS=7776000

# Partner portal: use a separate Zitadel application/client in the same project.
# The partner-api process reads the shared DEVFEED_OIDC_* policy settings;
# Compose maps these dedicated client values into that process only.
# DEVFEED_PARTNER_BASE_URL=https://partner.devfeed.tech
# DEVFEED_PARTNER_API_URL=http://partner-api:8004
# DEVFEED_PARTNER_PORT=3002
# DEVFEED_PARTNER_COOKIE_SECURE=true
# DEVFEED_PARTNER_SESSION_TTL_SECONDS=28800
# DEVFEED_PARTNER_OIDC_CLIENT_ID=
# DEVFEED_PARTNER_OIDC_CLIENT_SECRET=

# Server-only receipt signing key shared by the public API and user API delivery code.
# Use at least 32 random ASCII characters. Never expose this key to the reader or extensions.
# An empty key disables delivery and collection. See packages/core/PARTNER_PROMOTIONS.md.
DEVFEED_PARTNER_TRACKING_KEY=

# Dedicated server-only key shared by web and public API for caller quota isolation.
# Use at least 32 random ASCII characters; never reuse the receipt signing key.
DEVFEED_PARTNER_CALLER_KEY=
# Enable only behind an edge that overwrites this single-IP header and restricts origin access.
# Cloudflare Tunnel deployments can use cf-connecting-ip. Leave unset for direct development.
DEVFEED_PARTNER_CALLER_IP_HEADER=

# Optional partner connector credential, injected into import workers and admin API checks.
# Select this secret reference in the connector's authentication settings.
DEVFEED_PARTNER_SECRET_PRODUCTS_API_TOKEN=
# Encryption key for partner-provided import credentials. Generate a Fernet key
# with cryptography.fernet.Fernet.generate_key(); keep it separate from the DB.
# Inject the same key into partner-api and import workers. Missing configuration
# disables token setup; replacing the key requires replacing saved credentials.
DEVFEED_PARTNER_CREDENTIAL_KEY=
19 changes: 19 additions & 0 deletions .github/api-compatibility/admin-job-kinds.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Partner job kinds extend the shared AdminJobOut model. Existing requests retain
# their original kinds: /jobs/{kind} selects only that kind, and fixed analysis,
# notification and topic routes never return partner jobs. Partner kinds require
# an explicit new kind in the request. The generated admin client handles both.
# Scope exceptions to these two values and these exact response properties only.
GET /v1/admin/jobs/ai-analysis added the new `partner-evaluation` enum value to the `items/items/kind` response property for the response status `200`
GET /v1/admin/jobs/ai-analysis added the new `partner-pipeline` enum value to the `items/items/kind` response property for the response status `200`
GET /v1/admin/jobs/{kind} added the new `partner-evaluation` enum value to the `items/items/kind` response property for the response status `200`
GET /v1/admin/jobs/{kind} added the new `partner-pipeline` enum value to the `items/items/kind` response property for the response status `200`
GET /v1/admin/jobs/{kind}/{job_id} added the new `partner-evaluation` enum value to the `kind` response property for the response status `200`
GET /v1/admin/jobs/{kind}/{job_id} added the new `partner-pipeline` enum value to the `kind` response property for the response status `200`
POST /v1/admin/jobs/{kind}/{job_id}/retry added the new `partner-evaluation` enum value to the `kind` response property for the response status `200`
POST /v1/admin/jobs/{kind}/{job_id}/retry added the new `partner-pipeline` enum value to the `kind` response property for the response status `200`
POST /v1/admin/notifications/deliveries/{identifier}/retry added the new `partner-evaluation` enum value to the `kind` response property for the response status `200`
POST /v1/admin/notifications/deliveries/{identifier}/retry added the new `partner-pipeline` enum value to the `kind` response property for the response status `200`
POST /v1/admin/topic-proposals/{proposal_id}/analysis added the new `partner-evaluation` enum value to the `kind` response property for the response status `202`
POST /v1/admin/topic-proposals/{proposal_id}/analysis added the new `partner-pipeline` enum value to the `kind` response property for the response status `202`
POST /v1/admin/topics/{topic_id}/relationships/analysis added the new `partner-evaluation` enum value to the `kind` response property for the response status `202`
POST /v1/admin/topics/{topic_id}/relationships/analysis added the new `partner-pipeline` enum value to the `kind` response property for the response status `202`
36 changes: 32 additions & 4 deletions .github/images.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@
"apps/notifications/**",
"apps/article-enrichment-worker/**"
],
"platforms": ["linux/arm64"],
"platforms": [
"linux/arm64"
],
"smoke-script": ".github/scripts/smoke-image.sh"
},
{
Expand All @@ -54,7 +56,9 @@
"apps/notifications/**",
"apps/images-worker/**"
],
"platforms": ["linux/arm64"],
"platforms": [
"linux/arm64"
],
"smoke-script": ".github/scripts/smoke-image.sh"
},
{
Expand All @@ -77,15 +81,19 @@
"apps/notifications/**",
"apps/source-discovery-worker/**"
],
"platforms": ["linux/arm64"],
"platforms": [
"linux/arm64"
],
"smoke-script": ".github/scripts/smoke-image.sh"
},
{
"id": "mcp",
"image": "ghcr.io/abhi1693/devfeed.tech/mcp",
"context": ".",
"file": "apps/mcp/Dockerfile",
"platforms": ["linux/arm64"],
"platforms": [
"linux/arm64"
],
"smoke-script": ".github/scripts/smoke-image.sh"
},
{
Expand Down Expand Up @@ -137,6 +145,26 @@
"linux/arm64"
],
"smoke-script": ".github/scripts/smoke-image.sh"
},
{
"id": "partner-api",
"image": "ghcr.io/abhi1693/devfeed.tech/partner-api",
"context": ".",
"file": "apps/partner-api/Dockerfile",
"platforms": [
"linux/arm64"
],
"smoke-script": ".github/scripts/smoke-image.sh"
},
{
"id": "partner",
"image": "ghcr.io/abhi1693/devfeed.tech/partner",
"context": ".",
"file": "apps/partner/Dockerfile",
"platforms": [
"linux/arm64"
],
"smoke-script": ".github/scripts/smoke-image.sh"
}
]
}
24 changes: 21 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ jobs:
const url = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
const workspaces = [
'apps/admin-api', 'apps/aggregator', 'apps/api', 'apps/article-enrichment-worker',
'apps/cli', 'apps/images-worker', 'apps/mcp', 'apps/notifications',
'apps/cli', 'apps/images-worker', 'apps/mcp', 'apps/notifications', 'apps/partner-api',
'apps/search-indexer', 'apps/source-discovery-worker', 'apps/user-api',
'packages/core', 'packages/http'
];
Expand Down Expand Up @@ -178,6 +178,20 @@ jobs:
uv-sync-args: '["--all-packages"]'
generated-paths: '["apps/admin/openapi.json","apps/admin/src/lib/api/generated"]'
name: Unit / Admin UI lint, tests and build
partner-web:
name: Unit / Partner portal lint, tests, build and browser checks
uses: abhi1693/actions/.github/workflows/node-ci.yml@afba12afb85bf40be9328c92dc53b779f18d5c6d # v1.0.1
with:
checks: '["lint", "test", "build"]'
scripts: '{"lint": "partner:lint", "test": "ci:partner-test", "build": "ci:partner-browser"}'
timeout-minutes: 20
runs-on: ubuntu-24.04-arm
node-version: "24"
test-results-path: |
reports/partner.xml
reports/coverage/partner/lcov.info
test-results-name: partner-test-results-${{ github.run_attempt }}
project-env: '{"NEXT_TELEMETRY_DISABLED":"1"}'
user-web:
uses: abhi1693/actions/.github/workflows/node-ci.yml@afba12afb85bf40be9328c92dc53b779f18d5c6d # v1.0.1
with:
Expand Down Expand Up @@ -314,6 +328,7 @@ jobs:
allow-external-refs: false
review: false
github-token: ""
err-ignore: .github/api-compatibility/admin-job-kinds.txt
output-to-file: reports/api-compatibility/admin.breaking.txt
- name: Check public MCP
id: mcp_public
Expand Down Expand Up @@ -705,6 +720,7 @@ jobs:
- python-unit
- python-integration
- admin-web
- partner-web
- user-web
- browser-budgets
- dast
Expand All @@ -715,7 +731,7 @@ jobs:
if: >-
always() && !cancelled() &&
needs.python-unit.result == 'success' && needs.python-integration.result == 'success' &&
needs.admin-web.result == 'success' && needs.user-web.result == 'success' &&
needs.admin-web.result == 'success' && needs.partner-web.result == 'success' && needs.user-web.result == 'success' &&
((github.event_name == 'push' && github.ref == 'refs/heads/master') ||
(github.event_name == 'pull_request' &&
github.event.pull_request.head.repo.full_name == github.repository &&
Expand Down Expand Up @@ -821,6 +837,7 @@ jobs:
needs:
- python-unit
- admin-web
- partner-web
- user-web
- extensions
- python-integration
Expand Down Expand Up @@ -853,6 +870,7 @@ jobs:
- python-unit
- coverage-report
- admin-web
- partner-web
- user-web
- extensions
- api-compat
Expand Down Expand Up @@ -889,7 +907,7 @@ jobs:
RESULTS: ${{ toJSON(needs) }}
run: |
echo "$RESULTS" | jq -e --arg event "$EVENT_NAME" --arg ref_type "$REF_TYPE" --arg comment "$COVERAGE_COMMENT_REQUIRED" --arg browser_comment "$BROWSER_COMMENT_REQUIRED" --arg sonar "$SONAR_EXPECTED" '
([.["python-unit"], .["admin-web"], .["user-web"], .extensions,
([.["python-unit"], .["admin-web"], .["partner-web"], .["user-web"], .extensions,
.["python-integration"], .["migration-upgrade"], .["reader-parity"],
.["admin-browser"], .["live-browser"], .security]
| all(.result == "success")) and
Expand Down
38 changes: 10 additions & 28 deletions .github/workflows/performance.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,14 @@ jobs:
id: changes
run: node scripts/ci/api-performance-changes.mjs
measure:
name: ${{ matrix.revision }} sample ${{ matrix.repeat }}
name: Runner pair ${{ matrix.repeat }}
needs: select
if: github.event_name == 'pull_request' && needs.select.outputs.needed == 'true'
runs-on: ubuntu-24.04-arm
timeout-minutes: 10
timeout-minutes: 20
strategy:
fail-fast: false
matrix:
revision: [base, head]
repeat: [0, 1, 2]
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
Expand All @@ -44,7 +43,6 @@ jobs:
path: candidate
persist-credentials: false
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
if: matrix.revision == 'base'
with:
ref: ${{ github.event.pull_request.base.sha }}
path: baseline
Expand All @@ -59,45 +57,29 @@ jobs:
cache-dependency-glob: |
candidate/uv.lock
baseline/uv.lock
cache-suffix: performance-${{ matrix.revision }}
cache-suffix: performance-pair
- name: Install the candidate harness
run: sh candidate/scripts/ci/python-bootstrap.sh candidate --editable --all-packages --group loadtest
- name: Install the baseline application
if: matrix.revision == 'base'
run: sh candidate/scripts/ci/python-bootstrap.sh baseline --editable --all-packages
- name: Run one isolated sample
- name: Run one runner pair
env:
APP_ROOT: ${{ matrix.revision == 'base' && 'baseline' || 'candidate' }}
SAMPLE: ${{ matrix.revision }}-${{ matrix.repeat }}
run: |
destination="reports/performance/$SAMPLE"
mkdir -p "$destination"
set +e
candidate/.venv/bin/python candidate/scripts/load-test.py \
--app-root "$APP_ROOT" --app-python "$APP_ROOT/.venv/bin/python" \
--users 16 --spawn-rate 4 --seconds 60 --rows 1000 \
--output "$destination" > "$destination/runner.log" 2>&1
result=$?
printf '%s\n' "$result" > "$destination/exit-code.txt"
exit "$result"
PAIR_REPEAT: ${{ matrix.repeat }}
run: python3 candidate/scripts/ci/api-performance-pair.py --repeat "$PAIR_REPEAT"
- name: Preserve incomplete samples
if: always()
env:
SAMPLE: ${{ matrix.revision }}-${{ matrix.repeat }}
run: |
mkdir -p "reports/performance/$SAMPLE"
if [ ! -f "reports/performance/$SAMPLE/exit-code.txt" ]; then
echo incomplete > "reports/performance/$SAMPLE/exit-code.txt"
fi
PAIR_REPEAT: ${{ matrix.repeat }}
run: python3 candidate/scripts/ci/api-performance-pair.py --repeat "$PAIR_REPEAT" --preserve-only
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
if: always()
with:
name: perf-sample-${{ matrix.revision }}-${{ matrix.repeat }}-${{ github.run_attempt }}
name: perf-sample-pair-${{ matrix.repeat }}-${{ github.run_attempt }}
path: reports/performance/
if-no-files-found: error
retention-days: 30
compare:
name: Compare six independent samples
name: Compare six samples from three runners
needs: [select, measure]
if: always() && !cancelled() && github.event_name == 'pull_request'
runs-on: ubuntu-24.04
Expand Down
2 changes: 1 addition & 1 deletion .gitleaksignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ aefa7143e2d3420c702e54dd1906279f9b9c50ec:docs/development.md:generic-api-key:147
# Public RFC 6455 example WebSocket nonce in the historical transport test.
6f7042198d7a22e1fca9a6e100ed9571853adf8c:infra/codex/transport.test.cjs:generic-api-key:38

# Disposable partner-placement signing keys used only by historical test fixtures.
# Reviewed disposable fixture literals, replaced by generated test values.
9463cbb56414fc4f83ee6f183873bc39de323d2e:tests/test_partner_placement_api.py:generic-api-key:25
9463cbb56414fc4f83ee6f183873bc39de323d2e:tests/test_partner_placements_integration.py:generic-api-key:44
6 changes: 3 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ repos:
- id: check-yaml
args: [--allow-multiple-documents]
- id: end-of-file-fixer
exclude: ^apps/admin/src/lib/api/generated/
exclude: ^apps/(admin|partner)/src/lib/api/generated/
- id: trailing-whitespace
args: [--markdown-linebreak-ext=md]
exclude: ^apps/admin/src/lib/api/generated/
exclude: ^apps/(admin|partner)/src/lib/api/generated/

- repo: local
hooks:
Expand All @@ -42,7 +42,7 @@ repos:
entry: node node_modules/prettier/bin/prettier.cjs --write
language: system
files: \.(ts|tsx|js|jsx|mjs|cjs|mts|cts)$
exclude: (^|/)next-env\.d\.ts$|^apps/admin/src/lib/api/generated/
exclude: (^|/)next-env\.d\.ts$|^apps/(admin|partner)/src/lib/api/generated/
require_serial: true
- id: project-checks
name: Affected project lint, types and unit tests
Expand Down
2 changes: 2 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,5 @@ reports/
**/next-env.d.ts
apps/admin/openapi.json
apps/admin/src/lib/api/generated/
apps/partner/openapi.json
apps/partner/src/lib/api/generated/
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,23 @@ Application releases and Alembic schema revisions are separate identifiers.

- Label the user list's activity timestamp as Last active, reflecting authenticated activity rather than only sign-ins.

### Enhancements

- Set a separate sync interval for each partner without interrupting running syncs.
- Browse partner products in a searchable table with dedicated detail pages and related listings, jobs, and evaluations.
- Sync partner products independently so a failed product can retry without repeating successful work.
- Connect launch platform partnerships to sync developer products automatically, check product capabilities, and privately evaluate article relevance.
- Browse partnership pipeline jobs and evaluations in dedicated pages with related records, matching evidence, and worker logs.
- Manage partners in dedicated list, create, edit, and detail pages, with related products and sync job logs.
- Combine matching products from multiple launch platforms while retaining each listing, attribution, and shared product exclusions.

### Fixes

- Search partner products, pipeline jobs, and evaluations using literal text, including punctuation.
- Recover partner syncs after repeated failures so corrected upstream products can be discovered.
- Refresh article matching after retrying product checks while an earlier evaluation is still active.
- Sort products by name or update time in a partner's related objects.

## 0.0.48 — 2026-10-02

### Fixes
Expand Down
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ COPY packages/http/pyproject.toml packages/http/pyproject.toml
COPY apps/api/pyproject.toml apps/api/pyproject.toml
COPY apps/mcp/pyproject.toml apps/mcp/pyproject.toml
COPY apps/admin-api/pyproject.toml apps/admin-api/pyproject.toml
COPY apps/partner-api/pyproject.toml apps/partner-api/pyproject.toml
COPY apps/user-api/pyproject.toml apps/user-api/pyproject.toml
COPY apps/aggregator/pyproject.toml apps/aggregator/pyproject.toml
COPY apps/notifications/pyproject.toml apps/notifications/pyproject.toml
Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,11 @@ or [join the discussion](https://github.com/abhi1693/devfeed.tech/discussions).

Contributions to the reading experience, feed compatibility, accessibility, and
documentation are welcome. Start with [CONTRIBUTING.md](CONTRIBUTING.md).

## Partner portal

The standalone partner portal and API expose membership-scoped product/ad analytics,
and partnership tiers. Superusers manage accounts in the admin application. See [portal setup and access model](apps/partner/README.md).

Configure product API endpoints, mappings, pagination and authentication in the admin app.
See [partner API connectors](packages/core/PARTNER_CONNECTORS.md) for setup and supported contracts.
1 change: 1 addition & 0 deletions apps/admin-api/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ COPY packages/http/pyproject.toml packages/http/pyproject.toml
COPY apps/api/pyproject.toml apps/api/pyproject.toml
COPY apps/mcp/pyproject.toml apps/mcp/pyproject.toml
COPY apps/admin-api/pyproject.toml apps/admin-api/pyproject.toml
COPY apps/partner-api/pyproject.toml apps/partner-api/pyproject.toml
COPY apps/user-api/pyproject.toml apps/user-api/pyproject.toml
COPY apps/aggregator/pyproject.toml apps/aggregator/pyproject.toml
COPY apps/notifications/pyproject.toml apps/notifications/pyproject.toml
Expand Down
2 changes: 1 addition & 1 deletion apps/admin-api/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ version = "0.0.52"
description = "Isolated DevFeed administration and OIDC service"
requires-python = ">=3.12"
dependencies = [
"devfeed-core", "devfeed-http[identity]", "fastapi>=0.142.2,<1", "uvicorn[standard]>=0.34,<1",
"devfeed-core", "devfeed-http[identity,uploads]", "fastapi>=0.142.2,<1", "uvicorn[standard]>=0.34,<1",
"websockets>=15,<18", "rq>=2.8,<3",
]

Expand Down
Loading