-
-
Footer added by the Duo delivery agent: "Source (GitLab)" and "Original project" links, with the year computed automatically.
-
Only verified creators; every render is tied to an active, approved licence.
-
Creators page on prod: a labelled synthetic demo creator (Ana Reyes) that judges can license.
-
Prove it's you, set your terms, approve brands, get paid per render.
-
Brand dashboard: every render carries a KMS-signed receipt and a C2PA credential, verifiable on /verify.
-
Likeness: creators license their face to AI ads, approve every licence, get paid per render, and can revoke any time.
-
Creators set prices and allowed uses; brands license them in a few clicks.
Inspiration
Likeness lets creators license their face to AI ads: every licence is approved by the creator, every render is paid, and consent can be revoked any time. In this product a bug isn't downtime: it means someone's face used without permission. So after the code is written, every change is consent-critical. We wanted the whole post-code lifecycle to defend consent automatically, with a human approving the outcome.
What it does
Likeness (an existing MIT project, built 10–18 Oct for the Google AI Builder Cup) was imported to GitLab, and we built supervised, consent-aware delivery around it with the GitLab Duo Agent Platform:
- Likeness delivery (supervised): assign an issue to the agent; it implements it on a
duo/feature/*branch, reviews its own MR against our consent policy, and reports back. It has no merge tool. - Consent Guardian: reviews MRs against
CONSENT_POLICY.md(12 rules, read frommain, never the MR branch; diffs treated as untrusted data) and labels themconsent::safe,consent::revieworconsent::block. Aconsent-gateCI job turns that verdict into a hard gate. - Duo Fix CI/CD Pipeline (GitLab foundational flow): diagnoses failed pipelines and suggests the fix; a human applies it.
- Release & Monitor: after a green
mainpipeline, reads the staging smoke and consent end-to-end results and posts release notes on the source issue or MR, matching the GitLab Release. - Issue Triage: labels new issues, splits them into tasks, and flags consent-sensitive work for Guardian review.
The human gate is the merge (with a DCO sign-off) and a manual production deploy.
How we built it
- Verify: typecheck, 45 unit tests, 16 consent invariant tests running the real render, charge, receipt and verify code against in-memory Firestore, Storage and KMS stand-ins (with a real P-256 key).
- Secure: SAST, Secret Detection (full history), Dependency and Container Scanning. Container findings went from 1,004 to 162, critical from 9 to 0.
- Package: Docker image with SBOM, promoted by digest to Artifact Registry; a license check gates packaging.
- Configure / Release: Cloud Run staging and production, Firestore, Cloud KMS, Secret Manager, all created by an idempotent, guarded script. GitLab authenticates to Google Cloud with Workload Identity Federation (no keys). Every green
mainpipeline creates a GitLab Release. - Monitor: GitLab CI/CD observability, plus post-deploy smoke (10/10) and consent end-to-end (9/9) tests against staging.
- Govern: production deploys are pinned to the release approver's GitLab user via WIF, a deploy guard refuses the frozen production app, a per-pipeline audit report is kept for a year, and the consent policy lives in the repo as code.
Challenges we ran into
- Triggers only fire on human actions, so flows can't chain. We designed one multi-step delivery flow plus deliberate human touchpoints.
- Flow runtime: a slim container image without
curlstopped the agent from starting; we switched to GitLab's default image and added a CI check so it can't regress. - Release notes went nowhere at first: the flow had no tool to comment on an MR. We added it and a fallback order (issue, then MR, then a new issue).
- Composite identity makes flow-created MRs count as authored by the triggering human, so approval rules can't gate them. The merge itself became the documented gate.
- No protected environments for our role, and thousands of inherited Developers could run manual jobs, so we pinned production access to one GitLab user id at the Google Cloud level.
Accomplishments we're proud of
All nine DevSecOps stages run for real, with evidence in docs/STAGES.md. A change that removes the licence check is blocked twice: by the Consent Guardian (consent::block) and by four failing consent tests.
What we learned
Agents are most useful when their powers are narrow and explicit: read the policy from main, treat diffs as data, never merge. Deterministic tests and an AI reviewer complement each other.
What's next
Run the incident and rollback path of Release & Monitor on a real staging failure, and apply the same consent gates to the creator payout flow.
Built With
- artifact-registry
- c2pa
- cloud-kms
- cloud-run
- cyclonedx
- docker
- firebase-auth
- firestore
- gemini
- gitlab
- gitlab-ci
- gitlab-duo-agent-platform
- gitlab-observability
- google-cloud
- next.js
- node.js
- secret-manager
- semgrep
- trivy
- typescript
- veo
- vertex-ai
- vitest
- workload-identity-federation
Log in or sign up for Devpost to join the conversation.