soroush.asadi 62883ed01f Skill marketplace: publish, install, org-aware listing (+ adversarial-review fixes)
Orgs can now share skills across the tenant boundary — the next step after the per-org library.

Endpoints (all ManageSkills-gated + audited):
- POST /{key}/publish — list one of your published versions on the marketplace (Visibility→Public;
  only a Published/golden-tested skill may be listed). POST /{key}/unpublish reverses it.
- POST /install — copy a publicly-listed skill (by row id) into your org as a private Installed
  copy; rejects installing your own skill and duplicate (org+key+version) installs.
- GET /marketplace?organizationId= — other orgs' Authored+Public+Published skills (yours excluded),
  each flagged whether that exact (key, version) is already in your library.
- SkillSummary now carries Id (install targets a specific source row). Authored skills default to
  private — listing is an explicit publish step, never a side effect of authoring.

UI (Skills page): a Marketplace tab with Install / "In your library"; Publish / Unlist on your own
published skills; a "Listed" badge.

Fixes from the adversarial review (4 confirmed findings, all addressed):
- HIGH — Public⟹Published is now a domain invariant (Skill.Index forces PrivateToOrg whenever the
  re-derived status isn't Published), so re-authoring a listed version without golden tests can no
  longer leave it Public+Draft or decouple the marketplace gate from the eval gate.
- MEDIUM — install now uses an insert-only indexer path so the (org,key,version) unique index is the
  source of truth: a race with a concurrent install/author becomes a clean 409, never an in-place
  clobber of an existing row's content/ownership.
- MEDIUM/LOW — AlreadyInLibrary is computed per (key, version) to match the install conflict rule, so
  a newer, not-yet-owned version of a key you already hold still shows as installable.

Verified: ArchitectureTests 8/8, IntegrationTests 47/47 (SkillMarketplaceTests: publish gate, own-org
exclusion, cross-org list→install→private copy, duplicate 409, per-version flag, Public⟹Published
invariant, Member 403), client build green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 12:27:22 +03:30
2026-06-09 06:41:28 +03:30
2026-06-09 06:41:28 +03:30
2026-06-09 06:41:28 +03:30

TeamUp.AI

Build human + AI teams. A live org chart that does work: model the org, fill open role-seats with governed AI agents, run delivery on one board. A product of AliaSaaS.

Status: pre-M1 skeleton — the repo builds, tests green, and runs, but carries no feature code yet. See docs/V1_BUILD_PLAN.md for what M1M6 add.

Stack

.NET 10 modular monolith (web + worker on one image) · PostgreSQL 17 + pgvector · EF Core 10 · React 19 + Vite SPA into wwwroot · Docker Compose for local dev. Full bill of materials in docs/V1_BUILD_PLAN.md.

Layout

src/Shared/TeamUp.SharedKernel     IModule seam, base Entity, IModuleDbContext
src/Shared/TeamUp.Infrastructure   PlatformDbContext (pgvector + schemas), MigrationRunner, wiring
src/Bootstrap/TeamUp.Bootstrap     the explicit module catalog (the only thing that knows all modules)
src/Modules/TeamUp.Modules.*       OrgBoard · Identity · Skills · Assembler · Governance · Memory · Integrations
src/Hosts/TeamUp.Web               ASP.NET Core API host (also serves the SPA)
src/Hosts/TeamUp.Worker            Generic Host worker (background jobs; M4+)
client/                            React/Vite SPA → builds into TeamUp.Web/wwwroot
tests/                             ArchitectureTests (boundary rules) · IntegrationTests (Testcontainers)
docker/                            Dockerfile (one image, two roles) · docker-compose.yml

Boundary rule: each module is its own assembly; everything but its IModule and public contracts is internal, so no module can touch another's persistence. TeamUp.ArchitectureTests backstops this — it fails the build if a module references another module / Infrastructure / a host.

Prerequisites

.NET SDK 10 · Node 22 · Docker. Packages and container images are pulled through a Nexus mirror — see Package & image sources below.

Quick start

# Backend: build, run the boundary + integration tests (integration needs Docker)
dotnet build TeamUp.slnx
dotnet test  TeamUp.slnx

# Local dev — two terminals, with the Vite dev server proxying /api to the .NET host
docker compose -f docker/docker-compose.yml up postgres -d   # Postgres 17 + pgvector
dotnet run --project src/Hosts/TeamUp.Web                     # http://localhost:5180  (applies migrations in Dev)
cd client && npm install && npm run dev                       # http://localhost:5173  (proxies /api, /health)

# Or run the whole thing in containers (web + worker + postgres, single image, RUN_MODE picks the role)
docker compose -f docker/docker-compose.yml up --build

GET /health is the DB health check; GET /api/<module>/ping proves each module seam; the OpenAPI document is at /openapi/v1.json (Development only).

EF Core migrations

dotnet ef migrations add <Name> \
  --project src/Shared/TeamUp.Infrastructure --startup-project src/Shared/TeamUp.Infrastructure \
  --context PlatformDbContext --output-dir Persistence/Migrations

The initial InitialPlatform migration enables the vector extension and creates one schema per module. Module-owned contexts (M1+) get their own migrations and apply after Platform via MigrationRunner.

Package & image sources

NuGet packages (nuget.config) and container base images (docker/Dockerfile, docker/docker-compose.yml) are pulled through the self-hosted Nexus mirror mirror.soroushasadi.com, which proxies nuget.org / Docker Hub / MCR and is reachable from Iran. To build against the public registries instead, point nuget.config at api.nuget.org and replace the mirror.soroushasadi.com/... image prefixes with docker.io/library (node) and mcr.microsoft.com (dotnet). Testcontainers picks up the mirror via TESTCONTAINERS_HUB_IMAGE_NAME_PREFIX=mirror.soroushasadi.com/.

More

S
Description
No description provided
Readme 696 KiB
Languages
C# 67%
TypeScript 29.8%
CSS 2.6%
Dockerfile 0.3%
HTML 0.2%