Skip to content

Commit 79ba29a

Browse files
Merge branch 'main' into feature/multi-currency-price-feed
2 parents bafb194 + 23f3038 commit 79ba29a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+9021
-36
lines changed

.env.example

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# Server Config
2+
PORT=3000
3+
4+
# IPFS Config (Example using Infura)
5+
IPFS_HOST=ipfs.infura.io
6+
IPFS_PORT=5001
7+
IPFS_PROTOCOL=https
8+
IPFS_PROJECT_ID=your_infura_project_id
9+
IPFS_PROJECT_SECRET=your_infura_project_secret
10+
11+
# Stellar Config
12+
CONTRACT_ID=CAEGD57WVTVQSYWYB23AISBW334QO7WNA5XQ56S45GH6BP3D2AVHKUG4
13+
PORT=3000
14+
15+
# Auth configuration
16+
AUTH_JWT_SECRET=replace-with-a-long-random-secret
17+
AUTH_JWT_ISSUER=leaseflow-backend
18+
AUTH_JWT_AUDIENCE=leaseflow-users
19+
20+
# SQLite persistence
21+
DATABASE_FILENAME=./data/leaseflow-protocol.sqlite
22+
23+
# Lease renewal job
24+
LEASE_RENEWAL_JOB_ENABLED=false
25+
LEASE_RENEWAL_JOB_INTERVAL_MS=86400000
26+
LEASE_RENEWAL_SCAN_WINDOW_DAYS=0
27+
28+
# Soroban configuration
29+
SOROBAN_CONTRACT_ID=CAEGD57WVTVQSYWYB23AISBW334QO7WNA5XQ56S45GH6BP3D2AVHKUG4
30+
DISCORD_WEBHOOK_URL=your_discord_webhook_url_here
31+
# Algorand Configuration
32+
# Algorand Network Configuration
33+
ALGOD_TOKEN=
34+
ALGOD_SERVER=https://testnet-api.algonode.cloud
35+
ALGOD_PORT=443
36+
37+
# PostgreSQL Database Configuration
38+
DATABASE_URL=postgresql://username:password@localhost:5432/leaseflow_db
39+
# OR use individual variables:
40+
# DB_HOST=localhost
41+
# DB_PORT=5432
42+
# DB_NAME=leaseflow_db
43+
# DB_USER=username
44+
# DB_PASSWORD=password
45+
46+
# Email Configuration (for notifications)
47+
SMTP_HOST=smtp.gmail.com
48+
SMTP_PORT=587
49+
SMTP_SECURE=false
50+
SMTP_USER=your-email@gmail.com
51+
SMTP_PASS=your-app-password
52+
EMAIL_FROM=your-email@gmail.com
53+
54+
# SMS Configuration (Twilio)
55+
TWILIO_ACCOUNT_SID=your-twilio-account-sid
56+
TWILIO_AUTH_TOKEN=your-twilio-auth-token
57+
TWILIO_PHONE_NUMBER=+1234567890
58+
59+
# Owner Configuration (for auto-reclaim)
60+
# Owner Account (for executing reclaim transactions)
61+
OWNER_MNEMONIC=

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
node_modules
22
.env
3+
data
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# Lease Renewal Option Generator
2+
3+
## Overview
4+
5+
This feature adds an automated backend workflow that scans active leases approaching expiry, generates renewal proposals from landlord-defined rules, notifies both parties, and prepares the next Soroban lease contract payload after mutual acceptance.
6+
7+
## 60-Day Scan Behavior
8+
9+
- The renewal scan runs through `LeaseRenewalJob`.
10+
- The job evaluates active, renewable, non-disputed leases.
11+
- By default, a lease is eligible when it is exactly `notice_days` away from expiry.
12+
- `LEASE_RENEWAL_SCAN_WINDOW_DAYS` can widen the lower bound if operations want a small grace window.
13+
14+
## Renewal Rule Application
15+
16+
Each landlord can define one renewal rule with:
17+
18+
- `increase_type`: `percentage`, `fixed`, or `same`
19+
- `increase_value`
20+
- `term_months`
21+
- `notice_days`
22+
- `enabled`
23+
24+
The backend computes proposed terms on the server. Clients do not supply new rent or renewal dates.
25+
26+
## Duplicate Prevention / Idempotency
27+
28+
- Renewal proposals are keyed by `lease_id + target_start_date`.
29+
- The scan checks for an existing proposal for the same renewal cycle before generating a new one.
30+
- Re-running the job for the same day is safe and does not create duplicates.
31+
32+
## Notification Flow
33+
34+
When a proposal is generated, the backend persists one notification for:
35+
36+
- the landlord
37+
- the tenant
38+
39+
Each notification includes the lease reference, proposal reference, and a concise summary message.
40+
41+
## Agreement Flow
42+
43+
Available routes:
44+
45+
- `GET /renewal-proposals/:proposalId`
46+
- `POST /renewal-proposals/:proposalId/accept`
47+
- `POST /renewal-proposals/:proposalId/reject`
48+
49+
Only the proposal's landlord or tenant can view or act on it.
50+
51+
Status progression:
52+
53+
- `generated`
54+
- `landlord_accepted`
55+
- `tenant_accepted`
56+
- `fully_accepted`
57+
- `contract_prepared`
58+
- `rejected`
59+
- `expired`
60+
61+
## Soroban Contract Preparation
62+
63+
Once both parties accept:
64+
65+
- the backend prepares the next Soroban lease contract reference
66+
- the proposal is marked `contract_prepared` when successful
67+
- if preparation fails, the proposal remains `fully_accepted` and `soroban_contract_status` becomes `failed`
68+
69+
Tests mock Soroban behavior and do not require a live network.
70+
71+
## Scheduling Notes
72+
73+
- Enable automatic scheduling with `LEASE_RENEWAL_JOB_ENABLED=true`.
74+
- The interval is configured with `LEASE_RENEWAL_JOB_INTERVAL_MS`.
75+
- The default interval is once every 24 hours.
76+
77+
## Security Considerations
78+
79+
- Proposal ownership is enforced by signed bearer tokens and lease participant checks.
80+
- Landlords and tenants can only act on proposals tied to their own lease.
81+
- Renewal terms are server-generated from stored rules.
82+
- Duplicate generation is prevented for the same lease cycle.
83+
- Mutual acceptance is required before Soroban preparation.
84+
85+
## Limitations / Future Extensions
86+
87+
- The repository did not include an existing DB, notification bus, scheduler, or Soroban deployment stack, so this feature adds a focused SQLite-backed implementation and an injectable Soroban preparation service.
88+
- Automatic expiration sweeps can be added later if proposal expiry needs active enforcement.
89+
- If the project adopts a richer auth or job platform later, the current services provide clear seams for integration.

0 commit comments

Comments
 (0)