Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions .github/workflows/build-census-api.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,32 +18,32 @@ jobs:

steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
with:
# Pin to latest so the GHA cache v2 API is always supported (the
# legacy v1 service was shut down on 2025-04-15).
version: latest

- name: Log in to container registry
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
uses: docker/login-action@c99871dec2022cc055c062a10cc1a1310835ceb4 # v4.3.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract metadata
id: meta
uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0
uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6.2.0
with:
images: ${{ env.REGISTRY }}/${{ env.CENSUS_API_IMAGE }}
tags: |
type=raw,value=${{ github.run_id }}

- name: Build and push Docker image
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
with:
# Use the locally checked-out repo as build context instead of the
# default git context (which re-clones the repo inside BuildKit and
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/build-census-ui.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ jobs:

steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0

- uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8
- uses: pnpm/action-setup@008330803749db0355799c700092d9a85fd074e9 # v6.0.9
name: Install pnpm
with:
run_install: false
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/build-ipx.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,28 +18,28 @@ jobs:

steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0

- name: Log in to container registry
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
uses: docker/login-action@c99871dec2022cc055c062a10cc1a1310835ceb4 # v4.3.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract metadata
id: meta
uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0
uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6.2.0
with:
images: ${{ env.REGISTRY }}/${{ env.IPX_IMAGE }}
tags: |
type=raw,value=latest

- name: Build and push Docker image
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
with:
context: census/website/ipx
file: census/website/ipx/Dockerfile
Expand Down
12 changes: 6 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
environment: production
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
fetch-depth: 0

Expand All @@ -42,7 +42,7 @@ jobs:
name: ui-build
path: census/website/ui

- uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8
- uses: pnpm/action-setup@008330803749db0355799c700092d9a85fd074e9 # v6.0.9
name: Install pnpm
with:
run_install: false
Expand All @@ -56,15 +56,15 @@ jobs:
- name: Install dependencies
run: pnpm i

- uses: pulumi/auth-actions@1c89817aab0c66407723cdef72b05266e7376640 # v1.0.1
- uses: pulumi/auth-actions@141415910c3beb54e03b48e9057c204c97b956f2 # v2.1.0
name: Login to Pulumi
with:
organization: alveusgg
requested-token-type: urn:pulumi:token-type:access_token:personal
scope: user:changesbyjames

- name: Login to Azure
uses: azure/login@532459ea530d8321f2fb9bb10d1e0bcf23869a43 # v3.0.0
uses: azure/login@93381592711f247e165c389ebb30b596c84cdc48 # v3.0.0
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
Expand All @@ -91,7 +91,7 @@ jobs:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}

- name: Build & upload worker
uses: cloudflare/wrangler-action@9acf94ace14e7dc412b076f2c5c20b8ce93c79cd # v3.15.0
uses: cloudflare/wrangler-action@ebbaa1584979971c8614a24965b4405ff95890e0 # v4.0.0
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
packageManager: pnpm
Expand All @@ -104,7 +104,7 @@ jobs:
deploy --config wrangler.generated.jsonc --env prod

- name: Create Sentry release
uses: getsentry/action-release@5657c9e888b4e2cc85f4d29143ea4131fde4a73a # v3.6.0
uses: getsentry/action-release@ff07929a6537bac57790c3451cf4d364aca38528 # v3.7.0
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_ORG: alveus-sanctuary
Expand Down
60 changes: 60 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Contributing to Alveus Census

Thanks for your interest in contributing. This is an open community project and we welcome help from anyone who wants to get involved.

## Before You Start

For small fixes (typos, obvious bugs, minor improvements) just open a PR directly. For larger changes -- new features, architectural shifts, or anything that touches the data model -- open an issue first so we can talk through the approach before you invest a lot of time.

## Getting the Project Running

Follow the setup steps in [README.md](README.md). The short version:

```bash
pnpm install
pnpm run deps:up
cp census/api/.env.example census/api/.env
# Fill in census/api/.env, then:
pnpm --filter=@alveusgg/census-api setup:api
```

Then in two terminals:

```bash
pnpm --filter=@alveusgg/census-api dev
pnpm --filter=@alveusgg/census-website start
```

## Making Changes

- **Branch off `main`** and keep your branch focused on one thing.
- **Run the formatter** before pushing: `pnpm fmt` (or `pnpm fmt:check` to see what needs fixing).
- **Database migrations** -- if you change the schema, generate a migration with `pnpm --filter=@alveusgg/census-api db:generate` and include it in your PR.
- **Keep PRs small.** One logical change per PR makes review faster and easier to revert if needed.

## Opening a Pull Request

- Write a clear title and a short description of what you changed and why.
- If your PR closes an issue, link it in the description (`Closes #123`).
- Be responsive to review feedback -- we try to review promptly and expect the same in return.

## Code Style

The project uses [oxfmt](https://github.com/nicolo-ribaudo/oxfmt) for formatting. Run `pnpm fmt` and you're good. Beyond formatting, just try to match the style of the surrounding code.

## Reporting Bugs

Open a GitHub issue. Include:

- What you expected to happen
- What actually happened
- Steps to reproduce
- Environment info (Node version, OS, browser if relevant)

## Security Issues

Please do not report security vulnerabilities in public issues. See [SECURITY.md](SECURITY.md) for how to report them privately.

## Questions

If you're unsure about something, open an issue and ask. There are no dumb questions.
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 Alveus Sanctuary

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
122 changes: 122 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# Alveus Census

<img width="1263" height="332" alt="Alveus Census banner" src="https://github.com/user-attachments/assets/dc19e6ec-d5c3-4ba5-af06-ad1710cd2ad6" />

A monorepo for Alveus Census research projects, starting with the Alveus Pollinator Census -- a community-driven citizen science platform where viewers identify and document wildlife from live camera feeds.

## What Is This

The pollinator census lets the Alveus community submit Twitch clips from the pollinator garden, identify the insects in them, vote on each other's identifications, and earn points for contributing. Think crowdsourced species logging, gamified.

## Repo Structure

```
alveusgg-census/
├── census/
│ ├── api/ # Fastify + tRPC backend, PostgreSQL via Drizzle ORM
│ ├── website/ # React + Vite frontend
│ ├── forms/ # Shared Zod form schemas
│ └── levels/ # Points, levels, and achievement definitions
├── shared/
│ ├── backstage/ # Suspense-based async component utilities
│ ├── node/ # AsyncLocalStorage context helpers
│ └── errors/ # Shared error types
├── infrastructure/
│ └── pulumi/ # Azure + Cloudflare infrastructure as code
├── local/ # Docker Compose configs for local dev services
└── docs/ # Architecture and developer docs
```

## Tech Stack

- **Backend** -- Fastify, tRPC, PostgreSQL, Drizzle ORM, S3-compatible storage, Mux for video
- **Frontend** -- React 18, Vite, Tailwind CSS, Radix UI, tRPC client, React Query
- **Infrastructure** -- Azure (API), Cloudflare Workers (website), Pulumi for IaC
- **Auth** -- Alveus Auth (OIDC/OAuth2), Twitch API for clip retrieval

## Getting Started

### Prerequisites

- Node.js 22
- pnpm (`npm install -g pnpm`)
- Docker (for local services)
- ffmpeg installed locally

### Setup

```bash
# Install dependencies
pnpm install

# Start local services (Postgres + MinIO)
pnpm run deps:up

# Configure the API
cp census/api/.env.example census/api/.env
# Edit census/api/.env with your credentials

# Seed an admin user
pnpm --filter=@alveusgg/census-api setup:api
```

### Running Locally

```bash
# Start the API (watch mode)
pnpm --filter=@alveusgg/census-api dev

# Start the website (watch mode)
pnpm --filter=@alveusgg/census-website start
```

The API runs on `http://localhost:3000` and the website on `http://localhost:5173` by default.

### Optional: Video Streaming

If you want to test capture/clip functionality locally:

```bash
pnpm run stream:up
```

This starts MediaMTX for local RTMP/HLS streaming.

## Database

Migrations run automatically on API startup via Drizzle. To generate a new migration after changing the schema:

```bash
pnpm --filter=@alveusgg/census-api db:generate
```

## Environment Variables

See [`census/api/.env.example`](census/api/.env.example) for all available options. Required ones to get started:

- `POSTGRES_*` -- database connection
- `S3_*` -- object storage (MinIO locally)
- `ALVEUS_AUTH_*` -- OIDC auth provider
- `TWITCH_CLIENT_ID` / `TWITCH_CLIENT_SECRET` -- for clip retrieval

## Deployment

The project deploys via GitHub Actions on push to `main`:

- API to Azure Container Instances (via Pulumi)
- Website to Cloudflare Workers
- Infrastructure changes via Pulumi apply

See [`.github/workflows/`](.github/workflows/) for the full pipeline.

## Contributing

See [CONTRIBUTING.md](CONTRIBUTING.md) for how to get involved.

## Security

Found a vulnerability? See [SECURITY.md](SECURITY.md) for how to report it responsibly.

## License

MIT -- see [LICENSE](LICENSE).
29 changes: 29 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Security Policy

## Reporting a Vulnerability

If you find a security vulnerability in this project, please do not open a public GitHub issue. Public disclosure before a fix is in place puts users at risk.

Instead, report it privately by emailing **[email protected]**. Include:

- A description of the vulnerability and its potential impact
- Steps to reproduce or a proof of concept
- Any suggested fix if you have one

We will acknowledge your report within 48 hours and aim to have a fix or mitigation in place within 14 days depending on severity and complexity. We will keep you updated as we work on it.

Once a fix is released, we are happy to credit you in the release notes if you would like.

## Scope

This policy covers:

- The Alveus Census API (`census/api/`)
- The Alveus Census website (`census/website/`)
- Infrastructure configuration (`infrastructure/`)

Out of scope: third-party services and dependencies (Twitch, Mux, Cloudflare, Azure). Report those directly to the respective vendors.

## Supported Versions

We maintain only the latest version of the project. There are no versioned releases with separate security support windows.
Loading