Skip to content

Commit 1790067

Browse files
authored
Merge branch 'main' into feat/CM-361-part-1
2 parents c1cea25 + 8970c7e commit 1790067

41 files changed

Lines changed: 2546 additions & 153 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

backend/.env.dist.composed

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,6 @@ CROWD_PACKAGES_DB_PORT=5432
3535
CROWD_PACKAGES_DB_USERNAME=postgres
3636
CROWD_PACKAGES_DB_PASSWORD=example
3737
CROWD_PACKAGES_DB_DATABASE=packages-db
38+
39+
# security-contacts-worker
40+
SECURITY_CONTACTS_USER_AGENT="lfx-security-contacts-worker"

backend/.env.dist.local

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,9 @@ ENRICHER_BATCH_SIZE=100
185185
ENRICHER_REPO_UPDATE_INTERVAL_HOURS=24
186186
ENRICHER_IDLE_SLEEP_SEC=60
187187

188+
# security-contacts-worker
189+
SECURITY_CONTACTS_USER_AGENT="lfx-security-contacts-worker"
190+
188191
OSSPCKGS_GCP_PROJECT=local-dev
189192
OSSPCKGS_GCS_BUCKET=local-dev
190193
OSSPCKGS_GCP_CREDENTIALS_B64=e30=
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
CREATE TABLE IF NOT EXISTS security_contacts (
2+
id BIGSERIAL PRIMARY KEY,
3+
repo_id BIGINT NOT NULL REFERENCES repos(id) ON DELETE CASCADE,
4+
channel TEXT NOT NULL,
5+
value TEXT NOT NULL,
6+
role TEXT NOT NULL,
7+
name TEXT,
8+
score NUMERIC(4,3) NOT NULL,
9+
confidence TEXT NOT NULL,
10+
provenance JSONB NOT NULL DEFAULT '[]',
11+
last_refreshed TIMESTAMPTZ NOT NULL DEFAULT NOW(),
12+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
13+
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
14+
);
15+
16+
CREATE UNIQUE INDEX IF NOT EXISTS security_contacts_repo_channel_value_uq
17+
ON security_contacts (repo_id, channel, value);
18+
19+
CREATE INDEX IF NOT EXISTS security_contacts_repo_confidence_idx
20+
ON security_contacts (repo_id, confidence);
21+
22+
ALTER TABLE repos ADD COLUMN IF NOT EXISTS pvr_enabled BOOL;
23+
ALTER TABLE repos ADD COLUMN IF NOT EXISTS security_policy_url TEXT;
24+
ALTER TABLE repos ADD COLUMN IF NOT EXISTS vulnerability_reporting_url TEXT;
25+
ALTER TABLE repos ADD COLUMN IF NOT EXISTS bug_bounty_url TEXT;
26+
ALTER TABLE repos ADD COLUMN IF NOT EXISTS security_txt_url TEXT;
27+
ALTER TABLE repos ADD COLUMN IF NOT EXISTS contacts_last_refreshed TIMESTAMPTZ;
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
ALTER TABLE security_contacts ADD COLUMN IF NOT EXISTS deleted_at TIMESTAMPTZ;
2+
3+
CREATE INDEX IF NOT EXISTS security_contacts_repo_active_idx
4+
ON security_contacts (repo_id)
5+
WHERE deleted_at IS NULL;

pnpm-lock.yaml

Lines changed: 7 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

scripts/builders/packages.env

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
DOCKERFILE="./services/docker/Dockerfile.packages"
22
CONTEXT="../"
33
REPO="sjc.ocir.io/axbydjxa5zuh/packages"
4-
SERVICES="github-repos-enricher bq-dataset-ingest npm-worker maven-worker osv-worker dockerhub-sync cargo-worker go-worker nuget-worker"
4+
SERVICES="github-repos-enricher bq-dataset-ingest npm-worker maven-worker osv-worker dockerhub-sync cargo-worker go-worker nuget-worker security-contacts-worker"
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
version: '3.1'
2+
3+
x-env-args: &env-args
4+
DOCKER_BUILDKIT: 1
5+
NODE_ENV: docker
6+
SERVICE: security-contacts-worker
7+
SHELL: /bin/sh
8+
SUPPRESS_NO_CONFIG_WARNING: 'true'
9+
CROWD_TEMPORAL_TASKQUEUE: packages-worker
10+
11+
services:
12+
security-contacts-worker:
13+
build:
14+
context: ../../
15+
dockerfile: ./scripts/services/docker/Dockerfile.packages
16+
command: 'pnpm run start:security-contacts-worker'
17+
working_dir: /usr/crowd/app/services/apps/packages_worker
18+
env_file:
19+
- ../../backend/.env.dist.local
20+
- ../../backend/.env.dist.composed
21+
- ../../backend/.env.override.local
22+
- ../../backend/.env.override.composed
23+
environment:
24+
<<: *env-args
25+
restart: always
26+
networks:
27+
- crowd-bridge
28+
29+
security-contacts-worker-dev:
30+
build:
31+
context: ../../
32+
dockerfile: ./scripts/services/docker/Dockerfile.packages
33+
command: 'pnpm run dev:security-contacts-worker'
34+
working_dir: /usr/crowd/app/services/apps/packages_worker
35+
env_file:
36+
- ../../backend/.env.dist.local
37+
- ../../backend/.env.dist.composed
38+
- ../../backend/.env.override.local
39+
- ../../backend/.env.override.composed
40+
environment:
41+
<<: *env-args
42+
hostname: security-contacts-worker
43+
networks:
44+
- crowd-bridge
45+
volumes:
46+
- ../../services/libs/audit-logs/src:/usr/crowd/app/services/libs/audit-logs/src
47+
- ../../services/libs/common/src:/usr/crowd/app/services/libs/common/src
48+
- ../../services/libs/common_services/src:/usr/crowd/app/services/libs/common_services/src
49+
- ../../services/libs/data-access-layer/src:/usr/crowd/app/services/libs/data-access-layer/src
50+
- ../../services/libs/database/src:/usr/crowd/app/services/libs/database/src
51+
- ../../services/libs/integrations/src:/usr/crowd/app/services/libs/integrations/src
52+
- ../../services/libs/logging/src:/usr/crowd/app/services/libs/logging/src
53+
- ../../services/libs/nango/src:/usr/crowd/app/services/libs/nango/src
54+
- ../../services/libs/opensearch/src:/usr/crowd/app/services/libs/opensearch/src
55+
- ../../services/libs/queue/src:/usr/crowd/app/services/libs/queue/src
56+
- ../../services/libs/redis/src:/usr/crowd/app/services/libs/redis/src
57+
- ../../services/libs/snowflake/src:/usr/crowd/app/services/libs/snowflake/src
58+
- ../../services/libs/telemetry/src:/usr/crowd/app/services/libs/telemetry/src
59+
- ../../services/libs/temporal/src:/usr/crowd/app/services/libs/temporal/src
60+
- ../../services/libs/types/src:/usr/crowd/app/services/libs/types/src
61+
- ../../services/apps/packages_worker/src:/usr/crowd/app/services/apps/packages_worker/src
62+
63+
networks:
64+
crowd-bridge:
65+
external: true

services/apps/git_integration/src/crowdgit/database/crud.py

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,7 @@ async def find_github_identity(github_username: str):
335335
WHERE
336336
platform = 'github'
337337
AND value = $1
338+
AND "verified" = TRUE
338339
AND "deletedAt" is null
339340
LIMIT 1
340341
"""
@@ -406,18 +407,45 @@ async def update_maintainer_run(repo_id: str, maintainer_file: str):
406407

407408

408409
async def get_maintainers_for_repo(repo_id: str):
410+
# Active rows only (endDate IS NULL) — reappearing maintainers hit the "new"
411+
# branch and get reactivated by upsert_maintainer's ON CONFLICT clause.
412+
# verified=TRUE mirrors find_github_identity / find_maintainer_identity_by_email.
413+
# platform/type are returned so the diff's safety guard can match identifiers
414+
# by kind and avoid cross-platform value collisions (e.g. a GitHub username
415+
# "foo" colliding with a same-named handle on another platform).
409416
maintainers_sql_query = """
410-
SELECT mi.role, mi."originalRole", mi."repoUrl", mi."repoId", mi."identityId", mem.value as github_username
417+
SELECT mi.role, mi."originalRole", mi."repoUrl", mi."repoId", mi."identityId",
418+
mem.value as identity_value, mem.platform, mem.type
411419
FROM "maintainersInternal" mi
412420
JOIN "memberIdentities" mem ON mi."identityId" = mem.id
413-
WHERE mi."repoId" = $1 AND mem.platform = 'github' AND mem.type = 'username' and mem.verified = True AND mem."deletedAt" is null
421+
WHERE mi."repoId" = $1
422+
AND mi."endDate" IS NULL
423+
AND mem."verified" = TRUE
424+
AND mem."deletedAt" is null
414425
"""
415426
return await query(
416427
maintainers_sql_query,
417428
(repo_id,),
418429
)
419430

420431

432+
async def get_github_maintainer_usernames_for_repo(repo_id: str) -> set[str]:
433+
"""Return GitHub usernames of active maintainers for fork/parent-repo filtering."""
434+
sql_query = """
435+
SELECT mem.value
436+
FROM "maintainersInternal" mi
437+
JOIN "memberIdentities" mem ON mi."identityId" = mem.id
438+
WHERE mi."repoId" = $1
439+
AND mi."endDate" IS NULL
440+
AND mem.platform = 'github'
441+
AND mem.type = 'username'
442+
AND mem."verified" = TRUE
443+
AND mem."deletedAt" is null
444+
"""
445+
rows = await query(sql_query, (repo_id,))
446+
return {row["value"] for row in rows}
447+
448+
421449
async def set_maintainer_end_date(
422450
repo_id: str, identity_id: str, role: str, change_date: datetime
423451
):

0 commit comments

Comments
 (0)