Skip to content

Time Tracking & Billing

This document is the seed of the Meseta handbook. It will move to the shared Meseta vault when that vault is spun up. Path semantics (handbook/) are designed to be portable.

Why this matters

Time tracking at Meseta serves three purposes, in this order:

  1. Honest billing. Clients trust us because our invoices reflect work that actually happened.
  2. Engineer dignity. Tracking should be low-friction and low-surveillance. We don't watch screens, we don't enforce timers, we don't measure productivity by hours logged.
  3. Business intelligence. Engagement profitability, capacity planning, rate calibration.

If a tracking practice doesn't serve at least one of these, we drop it.

Stack

  • Tracking: Toggl Track Premium
  • Invoicing & payments: Mercury Invoicing
  • Reconciliation: custom scripts in the Meseta ops repo, run monthly
  • Source of truth for rates: rates.yaml in the Meseta ops repo

Time entry policy

Increments

15 minutes. This is the smallest billable unit and the rounding granularity.

We round 15-minute increments because engineering work is interrupt-driven and fragmentary. Hourly rounding makes a 20-minute Slack debugging assist into either zero (engineer doesn't bother) or sixty (engineer rounds up and feels gross). Both erode trust. 15-minute increments let us track honestly.

The boutique signal is not increment size — it's tagging discipline, narrative quality on line items, and consistent invoicing rhythm. Those we hold to a high standard.

Unit of work

Blocks of time, tracked against a project, with a short narrative and category tags. We do not track per-ticket — work crosses domains (cloud, platform, engineering, IT) and forcing per-ticket discipline when no ticket system exists is theater.

Toggl entry structure

Every entry has four fields:

  • Client — top-level entity, e.g. Xenter
  • Project — engagement-level, e.g. Xenter Cloud Platform, Xenter SDLC Compliance. Usually one or two per client.
  • Tag(s) — work category. Flat namespace, reusable across all projects: cloud, platform, it, security, meeting, docs, ops, architecture, code-review, support
  • Description — one sentence narrative. This is what becomes the invoice line item on detail reports. Examples:
    • "Argo CD app-of-apps refactor for pi-core"
    • "PHI vault threat model review with Xenter security team"
    • "GitHub Actions security scanning rollout — repos 4–7"

Bad descriptions: "work", "infra stuff", "meeting", blank.

Billable vs. non-billable

Every entry is one or the other. Default is set at the project level. Overridable per-entry when needed.

  • Non-billable by default: internal Meseta work (sales calls, our own tooling, admin, this handbook), unpaid kickoff time written into a SOW, internal training.
  • Billable by default: all client engagement work.

If you're unsure, mark it billable and flag it for review. It's easier to mark down than mark up.

Same-day entry rule

Time gets logged the day it happens. Backfilling more than 48 hours requires a note in the description explaining why (e.g., "logged Wednesday — was in the field with no laptop"). This is enforced socially, not by tooling.

This is the single biggest determinant of data quality. Stale memory produces inflated estimates and embarrassing line items.

Minimum entry

15 minutes. Anything smaller gets folded into an adjacent block or into a daily admin/comms block.

Rate cards

Three dimensions, in priority order:

  1. Per-engineer base bill rate — set at onboarding, reviewed annually. Reflects seniority and market.
  2. Per-engagement override — some clients negotiate blended rates, volume discounts, or compliance premiums. Lives on the project in Toggl.
  3. Per-role override (rare) — e.g. an engineer doing PM work on a project where they normally engineer.

Source of truth

rates.yaml in the Meseta ops repo is canonical. Toggl is mirrored from it. The reconciliation script verifies Toggl matches the YAML before generating invoices and halts on drift.

yaml
# rates.yaml structure (illustrative)
engineers:
  - id: eng_001
    name: ...
    base_bill_rate: 200    # what we bill clients
    base_pay_rate: 120     # what we pay them (1099)
    spread: 80             # bookkeeping; computed
engagements:
  - id: xenter_cloud
    client: xenter
    default_bill_multiplier: 1.0
    overrides:
      - engineer: eng_001
        bill_rate: 225     # premium for compliance work

Contractor payout model

Fixed pay rate. Each engineer has their own pay $/hr stored in rates.yaml. Meseta keeps the spread between bill rate and pay rate.

This model is explicit, predictable for the engineer, and lets us absorb client rate negotiation without renegotiating with the engineer. The spread funds Meseta overhead, business development, contract risk, and margin.

Engineers see their own pay rate in rates.yaml (it's their data). They do not see other engineers' rates or the bill side. Founder owns rate-setting.

The reconciliation flow

End-to-end. Three human touchpoints; everything else is automation.

Daily

  1. Engineer tracks time as they work — Toggl desktop app, browser extension, or autotracker.
  2. 5pm Slack reminder (automated): "Review today's entries." Engineer fixes obvious issues.

Weekly (Friday)

  1. 4pm Friday automated DM to each engineer: their week summarized by project, plus flags:
    • Untagged entries
    • Empty descriptions
    • Suspiciously round numbers (e.g., five 8-hour entries with one-word descriptions)
    • Missing days
  2. Engineer fixes issues, submits week in Toggl (locks entries from edit without admin unlock).
  3. 5pm Friday PM digest (automated): all engineers' weeks summarized for the PM, with anything still flagged. PM does anomaly review (not line-item review). Approves or kicks back specific entries.

Monthly (1st of month)

  1. Reconciliation script runs (automated):
    • Pulls all billable entries from previous month via Toggl API
    • Groups by client → project → engineer
    • Validates rates against rates.yaml. Halts on mismatch.
    • Validates completeness: flags low-hour weeks, days with zero entries that were working days, lingering untagged entries
    • Generates draft invoice spec per client (JSON): summary lines per project + per-engineer-per-day detail backup
    • Posts to #meseta-billing Slack channel with diff vs. last month
  2. Founder review (10–15 min): scan specs, edit narratives, approve.
  3. Script creates invoices in Mercury via API in draft state (not sent).
  4. Founder visual check in Mercury, sends.

Post-send

  1. Mercury webhook on payment → script logs payment against invoice in records.
  2. Once paid: script computes contractor payout (engineer billable hours × pay rate).
  3. Founder approves payout, executes via Mercury. Money movement always has a human gate.

Annual

  1. January: pull Mercury 1099 data for any contractor over $600. File via Mercury's 1099 flow.

Approval workflow

Three layers, deliberately light:

LayerWhoWhenWhat
Self-reviewEngineerFriday before submit"This is accurate." Locks entries.
Anomaly reviewPMFriday afternoon, asyncCatches obvious oddities. Not line-item review.
Invoice reviewFounder1st of monthReviews invoice specs, not entries.

Critical: the founder does not approve weekly entries. That's a scaling trap and makes the PM role cosmetic. PM owns weekly. Founder owns monthly invoices.

If the founder finds themselves auditing individual entries at invoice time, the upstream review failed and we fix the upstream review.

Client-side deliverable

Default invoice attachment: one-page PDF — Meseta logo, line items grouped by project (e.g. "Cloud Platform Engineering — 47.25 hours @ $X/hr — $Y"), total, payment terms, remittance details (Mercury handles).

Detail report (on request, or default for compliance-sensitive clients): per-engineer-per-day rows. Each row: date, engineer, project, hours, concatenated descriptions for the day. Same data, expanded view.

For Xenter specifically: default to attaching detail on every invoice. IEC 62304 shops appreciate the paper trail and it costs us nothing once the script does both. Confirm with their finance contact at next billing cycle.

What we measure (internal only)

Beyond invoicing, the same data feeds:

  • Engagement P&L — bill revenue minus pay cost minus allocated overhead, per project, per month
  • Engineer utilization — billable hours / available hours, per engineer, per month. Target band, not maximum.
  • Tag distribution — what categories of work are we actually doing? (Drives capacity planning and SOW templates.)

These are reviewed by the founder monthly. They are not shared with engineers as individual scorecards. Aggregate insights inform team decisions.

Operating principles

  • Trust before precision. A 95%-accurate timesheet that engineers actually fill out beats a 99%-accurate one that they resent.
  • No surveillance. No screen recording, no GPS, no keystroke tracking, no forced timers. Toggl Premium supports a trust-based posture and we use it that way.
  • Automation owes humans, not the other way around. Every automation in the pipeline exists to save engineer time, not to police it.
  • Honest line items. If a description would embarrass us in front of the client, we rewrite it before sending. Better still, we write it well the first time.
  • Money movement is human-gated. Invoices send with founder approval. Contractor payouts execute with founder approval. The reconciliation script proposes; humans dispose.

Open items

  • [ ] Build rates.yaml and seed initial rates
  • [ ] Set up Toggl workspace, create initial projects, invite team
  • [ ] Provision Mercury Invoicing access tier (needs Plus or Pro for API write)
  • [ ] Write reconciliation script v1
  • [ ] Create #meseta-billing Slack channel
  • [ ] Configure Friday Slack DMs
  • [ ] Confirm detail-report default with Xenter finance contact
  • [ ] Decide on engagement-level non-billable allowances (e.g. kickoff hours)
  • branding.md — Meseta brand
  • meseta.md (in Rodeo vault root project area) — Meseta thesis and structure
  • rates.yaml — to be created in ops repo

Meseta Handbook