tpt-gets-nz

Go

NZ Government Electronic Tenders Service (GETS) platform — browse, filter, and bid on government procurement opportunities. Go + PostgreSQL backend with RealMe SAML 2.0 auth, Next.js 14 frontend.

0 stars0 forks0 watchersMIT License
dockergolanggovernment-procurementnew-zealandnextjsopen-sourcepostegresqlrealmesamltender-management

Languages

Go77.5%TypeScript19.4%PLpgSQL2.8%Makefile0.2%Dockerfile0.1%
README

app-gets — Government Electronic Tenders Service

A modern GETS tender management platform that connects New Zealand government agencies with verified suppliers through RealMe authentication.

Features

  • Browse Tenders: Search and filter government procurement opportunities from the NZ GETS API
  • Supplier Profiles: RealMe-verified supplier profiles with business details and specialities
  • Bid Submission: Submit competitive bids on open tenders with proposal documents
  • Alert Subscriptions: Get notified when new tenders match your criteria
  • Saved Searches: Save and reuse complex search filters
  • Supplier Dashboard: Central hub for alerts, bids, and profile management

Architecture

app-gets/
├── cmd/server/           # HTTP server entrypoint
├── internal/
│   ├── models/           # Domain types (Tender, Bid, Supplier, Award)
│   ├── repository/       # PostgreSQL data access layer
│   ├── services/         # Business logic (tender, bid, supplier services)
│   └── handlers/         # HTTP handlers with RealMe auth middleware
├── migrations/           # Database schema (Atlas-compatible)
├── web/                  # Next.js 14 frontend
├── Dockerfile            # Go backend container
└── docker-compose.yml    # Service composition

Tech Stack

  • Backend: Go 1.23, Chi router, pgx (PostgreSQL)
  • Auth: RealMe (SAML 2.0) — login and verified identity
  • Frontend: Next.js 14, React, TailwindCSS
  • Data: PostgreSQL with JSONB for flexible arrays
  • Infrastructure: Docker, docker-compose

Quick Start

Prerequisites

  • Go 1.23+
  • Node.js 20+
  • Docker & docker-compose
  • PostgreSQL (or Docker PostgreSQL)
  • RealMe certificates (dev mock available)

Setup

  1. Start the database:

    docker compose up -d postgres
    
  2. Run database migrations:

    atlas schema apply --dir file://migrations --url "postgres://tptnz:tptnz_dev@localhost:5432/tptnz?sslmode=disable"
    

    Or apply manually:

    psql "postgres://tptnz:tptnz_dev@localhost:5432/tptnz?sslmode=disable" -f migrations/001_init.sql
    
  3. Start the backend:

    go run ./cmd/server
    

    The API will be available at http://localhost:8082.

  4. Start the frontend (in a separate terminal):

    cd web
    npm install
    npm run dev
    

    The UI will be available at http://localhost:3002.

Docker (full stack)

docker compose -f docker-compose.yml -f packages/app-gets/docker-compose.yml up

API Endpoints

Authentication (RealMe)

| Method | Path | Description | |--------|------|-------------| | GET | /auth/login | Initiate RealMe login | | GET | /auth/callback | SAML callback handler | | GET | /auth/logout | Logout and destroy session | | GET | /auth/metadata | SAML metadata XML | | GET | /auth/status | Current auth status |

Tenders (Public)

| Method | Path | Description | |--------|------|-------------| | GET | /tenders | List/search tenders | | GET | /tenders/categories | Get tender categories | | GET | /tenders/{id} | Get tender details | | GET | /tenders/{id}/bids | List bids for a tender | | POST | /tenders/sync | Sync from external GETS API |

Tenders (Authenticated)

| Method | Path | Description | |--------|------|-------------| | POST | /tenders/{id}/bids | Submit a bid (verified only) |

Suppliers

| Method | Path | Description | |--------|------|-------------| | GET | /suppliers/profile | Get/create own profile | | PUT | /suppliers/profile | Update own profile | | GET | /suppliers/{id} | Get supplier by ID |

Dashboard

| Method | Path | Description | |--------|------|-------------| | GET | /dashboard | User dashboard (profile, bids, alerts) |

Alerts & Saved Searches

| Method | Path | Description | |--------|------|-------------| | GET | /alerts | List alert subscriptions | | POST | /alerts | Create alert subscription | | DELETE | /alerts/{id} | Delete alert subscription | | PUT | /alerts/{id}/toggle | Toggle alert active status | | GET | /saved-searches | List saved searches | | POST | /saved-searches | Save a search | | DELETE | /saved-searches/{id} | Delete saved search |

Environment Variables

| Variable | Default | Description | |----------|---------|-------------| | LISTEN_ADDR | :8082 | HTTP server listen address | | DATABASE_URL | postgres://... | PostgreSQL connection string | | FRONTEND_URL | http://localhost:3002 | CORS allowed origin | | REALME_ENVIRONMENT | mts | RealMe environment | | REALME_CERT_FILE | certs/sp.crt | Service provider cert | | REALME_KEY_FILE | certs/sp.key | Service provider key | | REALME_ENTITY_ID | http://localhost:8082/auth/metadata | SAML entity ID | | REALME_ACS_URL | http://localhost:8082/auth/callback | SAML ACS URL | | REALME_IDP_METADATA_URL | http://localhost:8081/metadata | IdP metadata URL |

Data Model

  • tenders: Government procurement opportunities with budget ranges, categories, and regions
  • suppliers: RealMe-verified business entities with service categories
  • bids: Supplier proposals linked to tenders with lifecycle status tracking
  • awards: Contract awards for winning bids
  • alert_subscriptions: Supplier-configured keyword/category/region matching rules
  • saved_searches: Persistent search queries for quick access

Security

  • RealMe Login: Required for all authenticated endpoints
  • RealMe Verified: Required for bid submission (high-value actions)
  • CORS: Restricted to configured frontend origin
  • Session: Server-side encrypted sessions with 30-minute expiry
  • SAML: Signed authentication assertions via RealMe IdP

RealMe Registration

To use this app with real RealMe identities (ITE or Production environments), you must register a Service Provider with the Department of Internal Affairs.

MTS (Messaging Test Site) — Development

  1. Generate a self-signed certificate and key:

    mkdir -p certs
    openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
      -keyout certs/sp.key -out certs/sp.crt \
      -subj "/CN=localhost" -addext "subjectAltName=DNS:localhost"
    
  2. In MTS, no formal registration is needed — use the mock IdP in packages/realme-go/testenv/ for local development.

  3. Start the mock IdP:

    cd packages/realme-go
    go run ./testenv/ -addr :8081
    
  4. Configure the app to use the mock IdP:

    REALME_IDP_METADATA_URL=http://localhost:8081/metadata
    

ITE (Integration Test Environment) — Pre-Production

  1. Log in to the RealMe Developer Portal and register a new service.
  2. Submit your SP metadata XML (available at GET /auth/metadata) to DIA.
  3. DIA will provide the ITE IdP metadata URL.
  4. Generate a proper certificate (not self-signed) using the naming convention: ite.{service-name}.{org-domain}.nz
  5. Configure environment variables:
    REALME_ENVIRONMENT=ite
    REALME_CERT_FILE=certs/ite.sp.crt
    REALME_KEY_FILE=certs/ite.sp.key
    REALME_IDP_METADATA_URL=<DIA-provided-ITE-url>
    

Production

Follow the ITE steps above, substituting:

REALME_ENVIRONMENT=production
REALME_CERT_FILE=certs/prod.sp.crt
REALME_KEY_FILE=certs/prod.sp.key
REALME_IDP_METADATA_URL=<DIA-provided-prod-url>