RFC Process
This repository is used to propose, discuss, and document significant changes or new features across projects within Stratorys.
Why Use the RFC Process?
The RFC (Request for Comments) process is a well-established method for introducing significant changes or new features in a structured and transparent manner. It encourages thorough discussion and feedback from all stakeholders before implementation begins. By using RFCs, we ensure that:
- Clarity: All aspects of a proposal, including its design, rationale, and potential impacts, are clearly documented.
- Collaboration: Multiple stakeholders can contribute to and review the proposal, ensuring that different perspectives are considered.
- Historical Record: Decisions and their rationale are recorded, providing a valuable reference for future decisions.
This process helps us maintain a high standard of quality and alignment across teams, ensuring that any changes are well-considered and agreed upon before work begins.
Summary of the Repository Structure
This repository is organized by projects, each containing its own set of RFCs. The src directory includes the following:
SUMMARY.md: The table of contents for all RFCs, generated automatically.- Project Directories: Each project has its own directory under
src/, containing RFCs and an optionalREADME.mdfor project-specific information.
Example Structure
src/
├── SUMMARY.md
├── project-a/
│ ├── 0001-initial-rfc.md
│ ├── 0002-another-feature.md
│ └── README.md
├── project-b/
│ ├── 0001-feature-1.md
│ └── README.md
How to Create a New RFC
To create a new RFC, follow these steps:
- Copy the RFC template (0000-template.md) to the
src/<project-name>/directory and rename it using the following format:####-rfc-title.md(where####is the next available RFC number). - Fill out each section of the template with the relevant details for your proposal.
- Run
python3 generate-summary.pyto automatically update the SUMMARY.md file and include your new RFC in the book. - Submit a pull request for review.
Introduction
RFC 0001: Initial RFC
- Authors: Lucas Jahier lucas.jahier@stratorys.com
- Status: Draft
- Created: Sat Aug 24 08:25:28 CEST 2024
Summary
One paragraph explanation of the feature.
Motivation
Explain why this change is necessary or desirable. Describe the problem it solves, the opportunity it creates, or the benefit it provides. This section should make a compelling case for why the change is worth pursuing.
Detailed Design
This is the core of the RFC. Describe the technical details of the proposed solution. Include diagrams, code examples, or algorithms if necessary. This section should be thorough enough for others to understand how the solution will be implemented.
Subsection (if needed)
Break down the design into further subsections if it helps in clarity. This could include different components of the system, interaction with existing features, etc.
Drawbacks
Discuss any potential downsides or risks associated with this proposal. What are the trade-offs? Are there any negative implications or challenges that might arise from this change?
Alternatives
Outline any alternative solutions that were considered and explain why they were not chosen. This demonstrates that the proposed solution is the best option after careful consideration of other possibilities.
Unresolved Questions
List any open issues or questions that need to be addressed before moving forward. This could include technical challenges, uncertainties in the design, or areas where further discussion is needed.
Impact
Discuss the expected impact of this change. How will it affect users, systems, workflows, or other features? Are there any performance considerations, dependencies, or migration strategies that need to be addressed?
Implementation Plan
(Optional) If relevant, outline the steps required to implement this RFC. Include timelines, milestones, or phases of the rollout.
Security Considerations
(Optional) Discuss any security implications of this proposal. Are there any risks to data privacy, integrity, or availability?
RFC 0002: Another Feature
Introduction
RFC 0002: Improvement
RFC 001: API Template for SaaS with User Authentication, Workspaces, and Stripe Integration
- Authors: Lucas Jahier lucas.jahier@stratorys.com
- Status: Draft
- Created: Sat Aug 24 09:09:29 CEST 2024
Summary
This RFC proposes the creation of a Rust-based API template using Axum and SQLx (PostgreSQL) for SaaS applications. The template will include features such as user authentication, workspace management (with the ability to enable/disable workspaces), and simple payment integration using Stripe. The goal is to streamline the development process for new SaaS ideas, allowing developers to focus on domain-specific logic by providing a reusable foundation for common SaaS functionalities.
Motivation
Building a SaaS application often requires implementing the same foundational features such as user authentication, workspace management, and payment processing. These features can be time-consuming and distract from developing the unique aspects of the application. By creating a robust API template that includes these common features, we can reduce development time, avoid repetitive tasks, and ensure a consistent, secure, and scalable foundation for future projects. This template will be especially useful for rapidly prototyping new ideas or spinning up new SaaS products.
Detailed Design
The API template will be built using the following components:
1. User Authentication
- Framework: Axum will be used to handle HTTP requests and responses.
- Database: SQLx with PostgreSQL will store user credentials and profile information.
- Features:
- User registration and login with hashed passwords.
- Token-based authentication for securing API endpoints.
- Email verification and password reset functionality.
- User settings management
2. Workspace Management
- Concept: Users can create and manage workspaces, which can be enabled or disabled.
- Database Schema: A
workspacestable will be linked to theuserstable with a many-to-one relationship. - Features:
- Create, update, and delete workspaces.
- Enable or disable workspaces, affecting access and functionality for users associated with the workspace.
3. Payment Integration with Stripe
- Features:
- Subscription management: Users can subscribe to a plan, with billing occurring monthly.
- Payment validation: When a user creates a new account, the system checks if the user has already paid and links the payment to the correct account.
- Payment entry creation: Automatically creates an entry in the database when a payment is processed.
- Subscription update: Automatic updating of subscription status each month.
- Billing page link: Users can access their Stripe billing page for managing their subscription.
4. API Structure
- Routes:
/auth: Handles user authentication-related actions./workspaces: Manages CRUD operations and toggling of workspaces./webhook/stripe: Handle stripe webhook call/payment: Integrates Stripe functionality, including payment processing and subscription management.
Implementation Plan
- Phase 1: Set up the project structure with Axum, SQLx, and basic user authentication.
- Phase 2: Implement workspace management with enable/disable functionality.
- Phase 3: Integrate Stripe for payment processing and subscription management.
- Phase 4: Test and document the template for easy adoption in future projects.
RFC 002: Light Feature Flag System for SaaS API Template
- Authors: Lucas Jahier lucas.jahier@jahier.dev
- Status: Accepted
- Created: Sat Aug 24 09:18:29 CEST 2024
Summary
This RFC proposes the implementation of a light feature flag system within the Rust-based SaaS API template. The feature flag system will enable developers to toggle features on or off for individual users, workspaces, or globally across the application. This system provides flexibility for rolling out new features, conducting A/B testing, and managing feature access based on user segments or subscription tiers.
Motivation
Feature flag systems are essential for modern SaaS applications, allowing for controlled and gradual deployment of new features. By enabling or disabling features dynamically without requiring code changes or redeployment, developers can reduce risk, perform A/B testing, and offer differentiated experiences to users. Integrating a light feature flag system into the API template will enhance the flexibility and manageability of feature rollouts and help in maintaining a stable production environment.
Detailed Design
1. Overview
The feature flag system will be a lightweight mechanism to control the availability of specific features within the application. Features can be toggled on or off based on the scope—globally, per workspace, or per user. The system will rely on a simple database-backed implementation to store and manage feature flags.
2. Database Schema
A new feature_flags table will be introduced to manage the feature flags:
CREATE TABLE feature_flags (
id SERIAL PRIMARY KEY,
feature_name TEXT NOT NULL,
is_enabled BOOLEAN NOT NULL DEFAULT FALSE,
scope TEXT NOT NULL,
scope_id UUID NULL,
UNIQUE (feature_name, scope, scope_id)
);
feature_name: A unique identifier for the feature (e.g.,"new_dashboard_ui").is_enabled: A boolean flag indicating whether the feature is enabled (TRUE) or disabled (FALSE).scope: The scope of the feature flag. It can beglobal,user, orworkspace.scope_id: The UUID of the user or workspace if the scope is specific. For global flags, this will beNULL.
3. API Endpoints
New API routes will be introduced for managing feature flags:
GET /feature_flags: Retrieves a list of all feature flags.POST /feature_flags: Creates or updates a feature flag.- Request Body:
{ "feature_name": "new_dashboard_ui", "is_enabled": true, "scope": "workspace", "scope_id": "workspace-uuid-1234" }
- Request Body:
GET /feature_flags/:feature_name: Checks the status of a specific feature flag.DELETE /feature_flags/:feature_name: Deletes a feature flag.
4. Checking Feature Flags in Code
Developers will use a middleware function to check if a feature is enabled before executing feature-specific code. This function will query the feature_flags table based on the provided scope and feature name.
Example function:
#![allow(unused)] fn main() { async fn is_feature_enabled( feature_name: &str, scope: &str, scope_id: Option<Uuid>, db: &PgPool ) -> Result<bool, sqlx::Error> { let query = match scope { "user" | "workspace" => sqlx::query!( "SELECT is_enabled FROM feature_flags WHERE feature_name = $1 AND scope = $2 AND scope_id = $3", feature_name, scope, scope_id ), "global" => sqlx::query!( "SELECT is_enabled FROM feature_flags WHERE feature_name = $1 AND scope = $2", feature_name, scope ), _ => return Ok(false), }; let flag = query.fetch_optional(db).await?; Ok(flag.map(|f| f.is_enabled).unwrap_or(false)) } }
5. Feature Flag Precedence
The feature flag system will prioritize feature availability in the following order:
- User-specific flag: Highest precedence.
- Workspace-specific flag: Applied if no user-specific flag is found.
- Global flag: Default if no specific flags exist for the user or workspace.
6. Example Use Cases
- Beta Testing: Enable a new feature only for specific users to gather feedback before a full release.
- Premium Features: Offer exclusive features to users with premium subscriptions by enabling the flag at the user level.
- Gradual Rollout: Slowly enable a feature for one workspace at a time to monitor stability before a wider deployment.
Implementation Plan
- Phase 1: Implement the database schema and basic API routes for managing feature flags.
- Phase 2: Integrate the feature flag checking mechanism into existing and new feature implementations.
- Phase 3: Test and validate the feature flag system to ensure it behaves correctly under different scenarios.
- Phase 4: (Optional) Develop a simple admin UI for managing feature flags.