Skip to main content
Version: RK Auto

Terms&Condition


Terms & Conditions Versioning System

Author(s)

  • Amarnath Garai

Last Updated Date

2026-05-20


SRS References

  • TBD

Version History

VersionDateChangesAuthor
1.02026-05-15Initial implementationAmarnath Garai
1.12026-05-20Updated Terms request and response contracts for semantic versioningAmarnath Garai

Feature Overview

Objective:
Provide a complete Terms & Conditions management system with versioning, mandatory acceptance during signup, forced re-acceptance when Terms are updated, and full audit tracking.

Scope:
This feature covers the complete lifecycle of Terms & Conditions management including:

  • Versioned Terms & Conditions storage and retrieval
  • Mandatory acceptance during user signup
  • Forced re-acceptance when Terms are updated
  • Admin/System update support
  • Full audit tracking of user acceptances
  • API-based workflow for frontend integration

Dependencies:

  • Database system (PostgreSQL/SQL Server)
  • User management system
  • Authentication and authorization system
  • Audit logging system

Requirements

  1. User cannot sign up without accepting Terms & Conditions
  2. Admin/System can create and update Terms & Conditions
  3. Every update creates a new Terms version using major, minor, and patch version fields
  4. Users must re-accept updated Terms before accessing system
  5. Acceptance history is preserved for audit purposes
  6. System tracks acceptance metadata (IP address, User Agent)
  7. API endpoints for fetching latest Terms, accepting Terms, and checking status
  8. Admin endpoints for managing Terms versions and viewing history
  9. Terms ID and version server-side validation

Design Specifications

  • UI/UX Design:

    • Signup page must display latest Terms & Conditions
    • Acceptance checkbox required for signup completion
    • Login workflow must show Terms acceptance screen if user has outdated version
    • Admin dashboard for Terms management and version history
  • Data Models:

    Terms & Conditions Table

    CREATE TABLE termsandconditions (
    id UUID PRIMARY KEY,
    majorversion INT NOT NULL,
    minorversion INT NOT NULL,
    patchversion INT NOT NULL,
    versionlabel VARCHAR(50) NOT NULL,
    title VARCHAR(255) NOT NULL,
    content TEXT NOT NULL,
    isactive BOOLEAN NOT NULL DEFAULT TRUE,
    createdby UUID NULL,
    createdat TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    effectivefrom TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    CONSTRAINT uq_terms_version UNIQUE (majorversion, minorversion, patchversion)
    );

    User Terms Acceptance Table

    CREATE TABLE usertermsacceptance (
    id UUID PRIMARY KEY,
    userid UUID NOT NULL,
    termsid UUID NOT NULL,
    majorversion INT NOT NULL,
    minorversion INT NOT NULL,
    patchversion INT NOT NULL,
    acceptedat TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    ipaddress VARCHAR(100),
    useragent TEXT,
    CONSTRAINT fkterms
    FOREIGN KEY (termsid)
    REFERENCES termsandconditions(id)
    );
  • API Interfaces:

    EndpointMethodParametersResponseResponse Status Codes
    /terms/latestGETNoneTermsAndConditionsResponse200, 500
    /terms/acceptPOSTtermsId (required, Guid)CommonResponse200, 400, 401, 500
    /terms/statusGETNoneTermsStatusResponse200, 401, 500
    /termsPOSTtitle, content, majorVersion, minorVersion, patchVersion, effectiveFromCommonResponse201, 400, 403, 500
    /terms/historyGETNoneList of TermsVersionHistory200, 403, 500
  • API Examples:

    1. Get Latest Terms

    GET /terms/latest

    Response:

    {
    "id": "c2f67f3d-0f11-4fd4-a5d2-b0c4d621bc77",
    "majorVersion": 1,
    "minorVersion": 2,
    "patchVersion": 0,
    "versionLabel": "1.2.0",
    "title": "Terms & Conditions",
    "content": "Full terms content...",
    "effectiveFrom": "2026-05-15T00:00:00Z"
    }

    C# Response Model

    public record TermsAndConditionsResponse
    {
    public Guid Id { get; init; }
    public int MajorVersion { get; init; }
    public int MinorVersion { get; init; }
    public int PatchVersion { get; init; }
    public string VersionLabel { get; init; } = string.Empty;
    public string Title { get; init; } = string.Empty;
    public string Content { get; init; } = string.Empty;
    public DateTime EffectiveFrom { get; init; }
    }

    2. Accept Terms

    POST /terms/accept

    Request:

    {
    "termsId": "c2f67f3d-0f11-4fd4-a5d2-b0c4d621bc77"
    }

    C# Request Model

    public record AcceptTermsRequest
    {
    public Guid TermsId { get; init; }
    }

    Response:

    {
    "status": 200,
    "message": "Terms accepted successfully"
    }

    C# Response Model

      public record CommonResponse
    {
    public int Status { get; init; }
    public string? Message { get; init; }
    }

    C# Acceptance Row Model

    public record UserAcceptTermsRow
    {
    public Guid TermsId { get; init; }
    public Guid UserId { get; init; }
    public int MajorVersion { get; init; }
    public int MinorVersion { get; init; }
    public int PatchVersion { get; init; }
    public string? IpAddress { get; init; }
    public string? UserAgent { get; init; }
    }

    3. Check User Terms Status

    GET /terms/status

    Response:

    {
    "isLatestAccepted": false,
    "acceptedVersionLabel": "1.1.0",
    "latestVersionLabel": "1.2.0",
    "requiresAcceptance": true
    }

    C# Response Model

    public record TermsStatusResponse
    {
    public bool IsLatestAccepted { get; init; }
    public string? AcceptedVersionLabel { get; init; }
    public string LatestVersionLabel { get; init; } = string.Empty;
    public bool RequiresAcceptance { get; init; }
    }

    4. Create New Terms Version (Admin)

    POST /terms

    Request:

    {
    "title": "Terms & Conditions",
    "content": "Updated terms content...",
    "majorVersion": 1,
    "minorVersion": 2,
    "patchVersion": 0,
    "effectiveFrom": "2026-05-15T00:00:00Z"
    }

    C# Request Model

    public record CreateTermsRequest
    {
    public string Title { get; init; } = string.Empty;
    public string Content { get; init; } = string.Empty;
    public int MajorVersion { get; init; }
    public int MinorVersion { get; init; }
    public int PatchVersion { get; init; }
    public DateTime EffectiveFrom { get; init; }
    }

    Response:

    {
    "status": 201,
    "message": "Terms created successfully"
    }

    C# Response Model

      public record CommonResponse
    {
    public int Status { get; init; }
    public string? Message { get; init; }
    }

    5. Get Terms Version History (Admin)

    GET /terms/history

    Response:

    [
    {
    "majorVersion": 1,
    "minorVersion": 0,
    "patchVersion": 0,
    "versionLabel": "1.0.0",
    "createdAt": "2026-01-01T00:00:00Z"
    },
    {
    "majorVersion": 1,
    "minorVersion": 1,
    "patchVersion": 0,
    "versionLabel": "1.1.0",
    "createdAt": "2026-03-01T00:00:00Z"
    }
    ]
  • Third-Party Integrations:
    None

  • Workflow:

    Signup Workflow

    User Opens Signup

    Fetch Latest Terms (GET /terms/latest)

    Display Terms & Conditions

    User Accepts Checkbox

    Create User

    Store Acceptance Record (POST /terms/accept)

    Signup Complete

    Terms Update Workflow

    Admin/System Updates Terms (POST /terms)

    New Terms Version Created

    Latest Version Changes

    Existing Users Marked as Outdated

    Users Must Re-Accept on Next Login

    Login Workflow

    User Login

    Check Accepted Version (GET /terms/status)

    Compare With Latest Version

    If Outdated (requiresAcceptance = true)

    Force Terms Acceptance Screen

    User Accepts Latest Terms ID (POST /terms/accept)

    Access Granted

Backend Logic

Get Latest Terms Query

SELECT *
FROM termsandconditions
WHERE isactive = TRUE
ORDER BY majorversion DESC, minorversion DESC, patchversion DESC
LIMIT 1;

Get User Accepted Version Query

SELECT majorversion, minorversion, patchversion
FROM usertermsacceptance
WHERE userid = @UserId
ORDER BY majorversion DESC, minorversion DESC, patchversion DESC
LIMIT 1;

Determine Acceptance Requirement Logic

If Accepted semantic version < Latest semantic version
=> Require Re-Acceptance

Recommended Middleware Logic

During:

  • Login
  • Token refresh
  • App startup

Check:

Has user accepted latest Terms version?

If not:

  • Return special error code (HTTP 403)
  • Include response code: TERMS_ACCEPTANCE_REQUIRED
  • Include latest version label

Example response:

{
"code": "TERMS_ACCEPTANCE_REQUIRED",
"message": "User must accept latest Terms & Conditions",
"latestVersionLabel": "1.2.0"
}

Recommended HTTP Status Codes

ScenarioStatusDescription
Success200Request successful
Created201Terms version created
Bad Request400Invalid version or parameters
Unauthorized401User not authenticated
Forbidden403Terms acceptance required
Server Error500Internal error

Security Considerations

  1. Validate Terms Server-Side: Always verify:

    • Terms ID exists in database
    • Version is active (isactive = TRUE)
    • Version is the latest or an allowed accepted version
  2. Track Acceptance Metadata:

    • Store IP address for audit trail
    • Store User Agent for device tracking
    • Timestamp all acceptances
  3. Enforce Acceptance on Critical Operations:

    • Block login if latest Terms not accepted
    • Block token refresh if latest Terms not accepted
    • Block API access if latest Terms not accepted
  4. Audit All Changes:

    • Log all Terms creation/updates
    • Log all user acceptances
    • Maintain immutable acceptance history
  5. Prevent Version Manipulation:

    • Validate the submitted Terms ID before accepting
    • Store the accepted major, minor, and patch version from the database record
    • Do not trust frontend-provided version labels or numbers during acceptance