tpt-biz-incorporate-nz

Go

Register a New Zealand company instantly via MBIE Companies Office API, authenticated with RealMe Verified Identity. Go backend + Next.js frontend.

0 stars0 forks0 watchersMIT License
company-registrationgolangincorporationmbienew-zealandnextjsnz-governmentopen-sourcerealmesaml

Languages

Go68.0%TypeScript28.6%PLpgSQL1.5%CSS1.5%Makefile0.3%Dockerfile0.2%
README

Instant Business Incorporation — App 5

Register a new New Zealand company instantly using your RealMe verified identity. Direct integration with the MBIE Companies Office API.

Architecture

┌─────────────────────────────────────────────────────┐
│                  Next.js Frontend                    │
│  (TypeScript, React Server Components, Tailwind)    │
└──────────────────┬──────────────────────────────────┘
                   │ HTTP (JSON API)
┌──────────────────▼──────────────────────────────────┐
│                 Go Backend (Chi)                    │
│  ┌─────────────┐  ┌──────────────┐  ┌───────────┐  │
│  │  Auth       │  │  Service     │  │  Repository│  │
│  │  Handlers   │  │  Layer       │  │  (pgx)    │  │
│  └──────┬──────┘  └──────┬───────┘  └─────┬─────┘  │
│         │                │                 │        │
│         ▼                ▼                 ▼        │
│   RealMe SAML       MBIE API          PostgreSQL    │
│   (Provider)       (companies)          (pgxpool)   │
└─────────────────────────────────────────────────────┘

Tech Stack

  • Backend: Go 1.23, Chi router, pgx (PostgreSQL), RealMe SAML
  • Frontend: Next.js 14, TypeScript, Tailwind CSS
  • Database: PostgreSQL 16 (via docker-compose)
  • External API: MBIE Companies Office (api.business.govt.nz)
  • Identity: RealMe Verified Identity (SAML 2.0)

Quick Start

Prerequisites

  • Go 1.23+
  • Node.js 20+ (with pnpm)
  • Docker and Docker Compose
  • RealMe certificates (for production, see below for dev)

1. Start Infrastructure

From the project root:

# Start PostgreSQL, Redis, NATS
make dev

2. Database Migration

# Run the initial schema migration
DATABASE_URL="postgres://tptnz:tptnz_dev@localhost:5432/tptnz?sslmode=disable" \
  atlas schema apply --dir "file://packages/app-biz-incorporate/migrations" \
  --url "$DATABASE_URL" --auto-approve

Or apply manually:

psql "postgres://tptnz:tptnz_dev@localhost:5432/tptnz?sslmode=disable" \
  -f packages/app-biz-incorporate/migrations/001_init.sql

3. Run the Backend

cd packages/app-biz-incorporate
DATABASE_URL="postgres://tptnz:tptnz_dev@localhost:5432/tptnz?sslmode=disable" \
  go run ./cmd/server

The server starts on http://localhost:8080.

4. Run the Frontend (optional, for development)

cd packages/app-biz-incorporate/web
pnpm install
pnpm dev

The frontend starts on http://localhost:3005.

5. Docker Compose (all-in-one)

# From project root
docker compose -f docker-compose.yml \
  -f packages/app-biz-incorporate/docker-compose.yml up

API Endpoints

All protected endpoints require a RealMe Verified Identity session.

Authentication

| Method | Path | Description | |--------|-------------------|---------------------------------| | GET | /auth/login | Initiate RealMe login | | GET | /auth/callback | RealMe SAML callback | | GET | /auth/logout | Clear session | | GET | /auth/metadata | SAML SP metadata XML | | GET | /auth/status | Current auth status (requires login) |

Incorporation (requires RealMe Verified)

| Method | Path | Description | |--------|-------------------------|---------------------------------| | POST | /incorporate | Submit incorporation request | | GET | /companies | List user's companies | | GET | /companies/search?q= | Search companies by name | | GET | /companies/{id} | Get company details |

POST /incorporate

Request body:

{
  "companyName": "Acme Technologies NZ Ltd",
  "entityType": "NZLIMITED",
  "registeredOffice": {
    "streetAddress": "123 Queen Street",
    "city": "Auckland",
    "postcode": "1010",
    "country": "New Zealand"
  },
  "addressForService": {
    "streetAddress": "123 Queen Street",
    "city": "Auckland",
    "postcode": "1010",
    "country": "New Zealand"
  },
  "directors": [
    {
      "fullName": "John Smith",
      "email": "john@example.com",
      "dateOfBirth": "1980-01-15",
      "address": {
        "streetAddress": "45 High Street",
        "city": "Wellington",
        "postcode": "6011",
        "country": "New Zealand"
      },
      "consent": true,
      "realMeHash": "abc123hash"
    }
  ],
  "shareholders": [
    {
      "fullName": "John Smith",
      "shareClass": "Ordinary",
      "numberOfShares": 100,
      "email": "john@example.com",
      "isEntity": false
    }
  ]
}

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>

Environment Variables

| Variable | Default | Description | |-----------------------------|----------------------------------------------|------------------------------------| | LISTEN_ADDR | :8080 | Server listen address | | DATABASE_URL | postgres://tptnz:tptnz_dev@localhost:5432/...| PostgreSQL connection string | | MBIE_API_KEY | dev-api-key | MBIE API key | | MBIE_BASE_URL | (empty, uses default) | Override MBIE API base URL | | REALME_ENVIRONMENT | mts | mts, ite, or production | | REALME_CERT_FILE | certs/sp.crt | Path to SP certificate | | REALME_KEY_FILE | certs/sp.key | Path to SP private key | | REALME_ENTITY_ID | http://localhost:8080/auth/metadata | SAML entity ID | | REALME_ACS_URL | http://localhost:8080/auth/callback | SAML ACS URL | | REALME_IDP_METADATA_FILE | (empty) | Local IdP metadata file | | REALME_IDP_METADATA_URL | http://localhost:8081/metadata (default) | IdP metadata URL |

Testing

# From the app directory
go test ./...

# With race detection
go test -race ./...

# Run specific test
go test -v ./internal/handlers/ -run TestValidateIncorporationRequest

Database Schema

The schema (migrations/001_init.sql) consists of three core tables:

  • companies — Tracks the full incorporation lifecycle (draft, submitting, registered, rejected, error)
  • directors — RealMe-verified natural persons with expressed consent
  • shareholders — Natural or corporate entities holding shares