- Knowledge
- technology
- OOP
- Tips
- Programming
- Tips
- Tutorial
- SEO
- Ranking
- Knowledge
- Special Day
- Seo
- Bug
- Data science
- Seo
- artificial intelligence
- Machine Learning
- Robotics
- happyNewYear2021
- newYearEve
- 2021
- Automation
- Smart Home
- Career
- Best Practices
- Git
- Logging
- Web Fundamentals
- DNS
- HTTPS
- Performance
- AI Tools
- ChatGPT
- Claude
- Gemini
- Laravel
- Eloquent
- MySQL
- HTTPS
- TLS
- Web Security
- Certificates
- Developer Life
- Debugging
- Docker
- DevOps
- Transactions
- Queues
- LLMs
- AI
- AI Coding
- Developer Tools
- React Native
- Expo
- Kate PMS
- Mobile Apps
- Laravel
- Authentication
- Sanctum
- Cookies
- API Design
- Payments
- Idempotency
- DeepSeek
- Open Source AI
- LLMs
- AI News
- Git
- Version Control
- AI Coding
- Prompting
- PHP
- Checklist
- MCP
- AI Agents
- OpenAI
- Architecture
- Microservices
- Modular Monolith
- Estimation
- Developer Life
- Project Planning
- Humour
- OAuth
- OpenID Connect
- Authentication
- Embeddings
- Vector Search
- RAG
- pgvector
- OpenAI
- GPT-4.1
- Codex CLI
- Events
- Testing
- Clean Code
- Maintainability
- Code Review
- Webhooks
- API
- Security
- Claude Code
- Workflow
- AI
- LLM
- Prompt Injection
- Mobile
- React
- Networking
- TCP
- UDP
- HTTP/3
- CLAUDE.md
- AWS
- Cloud Security
- Backups
- PHPUnit
- Software Engineering
- Leadership
- Communication
- RAG
- Embeddings
- AI Engineering
- IT Infrastructure
- Networking
- Access Control
- CI/CD
- GitHub Actions
- Gemini CLI
- Claude Code
- JavaScript
- Async/Await
- Node.js
- Promises
- Security
- Cryptography
- Passwords
- MySQL
- Database
- Vibe Coding
- Software Quality
- DNS
- Code Reading
- Onboarding
- Productivity
- Background Jobs
- Developer Humour
- Estimates
- Dev Life
- JWT
- o3-mini
- DeepSeek R1
- Rate Limiting
- Kate PMS
- E-Signing
- Audit Trail
- REST
- GraphQL
- API Design
- Laravel 12
- Upgrade Guide
- Open Source
- Self-Hosting
- Task Scheduling
- Cron
- Secrets
- CORS
- PHP
- PHP-FPM
- OPcache
- GitHub Copilot
- Software Architecture
- Engineering
- TypeScript
- JavaScript
- Type Safety
- AI Security
- React Native
- Product Design
- AI Agents
- Kiro
- Queues
- Redis
- RabbitMQ
- AWS SQS
- Nginx
- Apache
- GPT-5
- gpt-oss
- Clean Code
- Architecture
- Naming
- Documentation
- Career
- ADR
- Teamwork
- Supply Chain
- Kate HRM
- HR Software
- Permissions
- System Design
- Pagination
- SSH
- Linux
- Big O
- Databases
- Laravel Boost
- MCP
- Developer Skills
- Validation
- Databases
- Indexes
- Code Quality
- Deployment
- Developer Humour
- Feature Flags
- Code Review
- Pull Requests
- Docker
- Cursor
- Authorization
- RBAC
- Gemini
- Long Context
- PHP 8.4
- Caching
- Dependency Injection
- Web Performance
- Browser
- CSS
- Database
- Migrations
- ChatGPT
- AI for Developers
- Monitoring
- On-Call
- REST
- Backend
- SQL
- NoSQL
- Database Design
- Coding Agents
- Claude 4
- API Resources
- REST API
- Load Balancing
- Scaling
- AWS
- AI Tools
- Claude
- Sora 2
- CTE
- 2FA
- TOTP
- Programming Languages
- Prompts
- Developer Workflow
- API Gateway
- APIs
- Passport
- API Auth
- Learning
- Burnout
- Developer Growth
- Web Development
- SEO
- Kate Mall
- ChatGPT Atlas
- Agent Skills
- Middleware
- Laravel 12
- Collections
- Context Window
- Monitoring
- Commit Messages
- Self Review
- Growth
- Regex
- Programming Basics
- Text Processing
- Database Design
- Normalization
- Linux
- Server Security
- Linux Foundation
- Open Standards
- Legacy Code
- Documentation
- AI Workflow
- File Uploads
- Test Data
- Hashing
- Performance
- Caching
- Enums
- Scope Creep
- Estimation
- Codex
- Gemini CLI
- Timezones
- Carbon
- Bugs
- PHP 8.5
- Gemini 3
- GPT-5.1
- Data Integrity
- Event Loop
- Async
- Opus 4.5
- AI Models
- React
- Forms
- Frontend
- Backups
- AI Images
- DALL-E
- Midjourney
- Race Conditions
- Concurrency
- Legacy Code
- Refactoring
- Senior Engineer
- Scope
- LLM
- CDN
- Web
- Sub-Agents
- Soft Deletes
- Audit Log
- Concurrency
- AI Learning
- NestJS
- AI Evals
- Policies
- SPF DKIM DMARC
- Unicode
- UTF-8
- Knowledge Graph
- Value Objects
- Technical Debt
- Feature Flags
- Laravel Pennant
- Deployment
- Copilot
- Composer
- Dependencies
- Artisan
- Automation
- AWS S3
- Object Storage
- Cloud
- Small Language Models
- Ollama
- Production
- Sessions
- HTTP
- Mentoring
- SQL
- Virtual Machines
- Web Development
- HTTP/2
- QUIC
- Web Performance
- AI Integration
- LLM API
- SOLID
- OOP
- Hosting
- Serverless
- Merge Conflicts
- Temperature
- AI Development
- Reverse Proxy
- Nginx
- Infrastructure
- Verification
- Passkeys
- WebAuthn
- Teams
- Communication
- Stakeholders
- Monorepo
- CI/CD
- Versioning
- JSON Schema
- Livewire
- Inertia
- Meetings
- Distributed Systems
- Privacy
- Full-Stack
- T-Shaped Skills
- Money
- Notifications
- Web Security
- HTTP Headers
- CSP
- Function Calling
- Load Testing
- k6
- Data Extraction
- Debugging
- WebSockets
- SSE
- Real-Time
- Laravel Reverb
- Infrastructure as Code
- Terraform
- Side Projects
- Laravel Pint
- OpenAPI
- Swagger
- UX
- Multimodal
- Jest
- Pair Programming
- APIs
- Rate Limiting
- Resilience
- Dev Humour
- Design Tokens
- JWT
- API Keys
- Sessions
- PHPStan
- Rector
- Incidents
- Reporting
- Dashboards
- Zero Trust
- IAM
- Search
- Laravel Scout
- Junior Developers
- Mentoring
- Images
- WebP
- AVIF
- Bug Reports
- Let's Encrypt
- Design Docs
- Software Design
- Observers
- Replication
- Accountability
- Data Structures
- Reliability
- LLM Memory
- Error Handling
- Payments
- Payment Gateway
- Webhooks
- PCI DSS
- Observability
- OpenTelemetry
- Personal Brand
- Writing
- Conventions
- Dates
- Scheduling
- Disaster Recovery
- Compression
- Brotli
- Deadlines
- Developer Habits
- State Machines
- Tech Roles
- UUID
- ULID
- Horizon
- Planning
- Engineering Culture
- Ownership
- Soft Skills
- Socialite
- Cost Control
- Collations
- Unicode
- Octane
- PostgreSQL
Verifying Company Documents Before a Contract Gets Signed
About Post
An e-signature is very good at proving one thing: a specific person clicked "Sign" at a specific time. It says nothing about whether the company named at the top of the contract actually exists, is still active, or is spelled the way the law knows it.
For a residential lease with an individual, that's less of a concern. For a commercial lease, where the tenant is a company, it matters a lot. A contract with the wrong legal name, or with a company whose registration has expired, is the kind of problem nobody notices until the day someone needs to rely on that contract.
In Kate PMS, our property management system, contract signing includes a verification step against Commercial Registration (CR) records. Below is how I think about designing a step like this: the principles, not the internals.
Why verify at all?
When a company signs a lease, a few things need to be true:
- The company is real and registered.
- Its registration is valid on the day of signing, not expired.
- The name and CR number on the contract match the official record exactly.
Without a check, all of these depend on someone reading a scanned document carefully, every time, under deadline pressure. People are good at many things. Spotting that "Trading" became "Trade" in a company name on the fortieth contract of the week isn't one of them.
So the system does the boring comparison, and people handle the judgement calls.
Where it sits in the signing flow
The most important design decision is making verification a gate, not a checkbox. A contract for a company tenant moves through clear states, and it can't reach "ready to sign" without passing verification:
- Draft: staff prepare the contract with the company's details and CR number.
- Verification: the system compares those details with the Commercial Registration record.
- Verified or needs review: a clean match moves forward; anything else stops here with a clear reason.
- Sent for signing: only verified contracts go out for e-signature.
- Signed: the signed document and the verification result are stored together.
Modelling this as states, instead of a boolean like is_verified, pays off quickly. You can see where every contract is, the UI can only show actions that make sense in the current state, and there's no back door where a contract skips a step because someone called the wrong method.
What gets compared
The comparison focuses on the details that make a contract legally meaningful: the CR number, the registered company name and the validity of the registration on the signing date.
Comparing names sounds simple until you try it. The same company can appear with different spacing, punctuation, letter case, or abbreviations of its legal form. So before comparing, both sides are normalised to remove formatting noise.
The firm line to draw: normalisation removes noise, it never guesses. There is no "92% similar, close enough". If two names still differ after cleaning up spacing and punctuation, a human looks at it. Fuzzy matching is great for search boxes. It's the wrong tool for deciding who a legal contract is with.
Handling mismatches
Most of the design work goes here, because the happy path is easy. Every failure needs a clear outcome and a clear next step for staff:
| Situation | What happens |
|---|---|
| Everything matches and the CR is valid | Contract moves to signing |
| Name differs from the record | Held for review, showing both versions side by side |
| CR number not found | Held; staff check for a typo or ask the tenant for the correct document |
| Registration expired | Held; the tenant is asked for a renewed registration before signing |
| Verification couldn't run | Held and retried; never treated as a pass |
That last row matters more than it looks. When a check can't complete, it's tempting to let the contract through so work isn't blocked. That turns your safety check into a check that only works on good days. A failed check is "not verified", full stop.
The principle: a verification step must fail closed. "We couldn't check" should never quietly become "it's fine".
Overrides, with a paper trail
Real life is messy, and sometimes a mismatch has a legitimate explanation that staff can confirm another way. So the system allows an override, but only for roles that are permitted to make that call (Kate PMS uses role-based access throughout), and only with a written reason.
Every verification attempt is recorded: what was checked, when, the result, and if someone overrode it, who and why. When a question comes up months later, the answer is in the contract's history rather than in someone's memory.
Timing: verify close to signing
A registration can be valid when a contract is drafted and expired by the time it's signed, especially if negotiations take a while. So verification happens as the contract moves towards signing, and a contract that sits too long can be checked again before it goes out.
What I'd tell anyone building something similar
- Make verification a state in the workflow, not a flag someone can forget to check.
- Normalise formatting, never guess. Anything that isn't an exact match after cleanup goes to a person.
- Fail closed. An error, a timeout or a missing record is a hold, not a pass.
- Allow overrides, but make them deliberate: right role, written reason, permanent record.
- Show staff why something is held. "Verification failed" creates support tickets; "Registered name differs: see both versions" gets the problem fixed.
Software that handles contracts is mostly about trust: the landlord trusting the tenant is who they say, and staff trusting the system not to wave things through. A verification step that is strict, transparent and well recorded is a big part of earning that.
If you've built verification into a business workflow, how did you handle the cases that were "almost" a match?

Be first to comment it...