From 4343c76ffc65785885fa7c540767c076aadaba8c Mon Sep 17 00:00:00 2001
From: Steven Johnson
Date: Wed, 4 Dec 2024 13:34:36 +0700
Subject: [PATCH 01/25] docs(cat-gateway): Proposal schema templates WIP
---
.../proposal/proposal.F14.example.json | 105 +++++
.../proposal/proposal.F14.schema.json | 402 ++++++++++++++++++
.../proposal/proposalTemplate.F14.schema.json | 401 +++++++++++++++++
3 files changed, 908 insertions(+)
create mode 100644 docs/src/architecture/08_concepts/document_templates/proposal/proposal.F14.example.json
create mode 100644 docs/src/architecture/08_concepts/document_templates/proposal/proposal.F14.schema.json
create mode 100644 docs/src/architecture/08_concepts/document_templates/proposal/proposalTemplate.F14.schema.json
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/proposal.F14.example.json b/docs/src/architecture/08_concepts/document_templates/proposal/proposal.F14.example.json
new file mode 100644
index 00000000000..27a616b7cc3
--- /dev/null
+++ b/docs/src/architecture/08_concepts/document_templates/proposal/proposal.F14.example.json
@@ -0,0 +1,105 @@
+{
+ "$schema": "./proposalTemplate.F14.schema.json",
+ "template_version": {
+ "description": "The version of the schema, formatted as a ULID.",
+ "title": "Version",
+ "uid": "version_section",
+ "value": "01F8MECHZXK8F8D8F8D8F8D8F9"
+ },
+ "category_segment": {
+ "description": "Details about the categories related to the proposal.",
+ "title": "Category Segment",
+ "uid": "category_segment_section",
+ "value": {
+ "additional_questions": {
+ "description": "Details about additional questions regarding the project.",
+ "title": "Additional Questions",
+ "uid": "additional_questions_section",
+ "value": {
+ "is_open_source": true,
+ "license_type": "anything i please",
+ "product_repository_url": "http://somwhere.test/a/project/url",
+ "project_documentation_url": "http://somwhere.test/a/project/url/for/documentation"
+ }
+ },
+ "agreements": {
+ "description": "Terms and agreements for the proposal.",
+ "title": "Terms and Agreements",
+ "uid": "agreements_section",
+ "value": {
+ "agree_fund_rules": false,
+ "catalyst_terms_and_conditions": false,
+ "privacy_policy": true
+ }
+ },
+ "milestones": {
+ "description": "Milestones to track project progress.",
+ "title": "Project Milestones",
+ "uid": "milestones_section",
+ "value": [
+ {
+ "deliverables": [
+ "something",
+ "something else"
+ ],
+ "description": "a multi lin\\nstring",
+ "title": "a single line string"
+ }
+ ]
+ },
+ "resources": {
+ "description": "Information about resources and budget allocation.",
+ "title": "Resources and Budget",
+ "uid": "resources_section",
+ "value": {
+ "budget_breakdown": "multi\\nline\\nstring",
+ "project_team": [
+ {
+ "experience": "multi\\nline\\nstring",
+ "role": "manager"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "category_template": {
+ "description": "The category to which this template belongs.",
+ "title": "Category",
+ "uid": "category_section",
+ "value": "can_be_any_value_without_whitespace"
+ },
+ "proposal_setup_segment": {
+ "description": "Basic information about your proposal.",
+ "title": "Proposal Setup",
+ "uid": "proposal_setup_section",
+ "value": {
+ "proposal_title": {
+ "description": "The name of the proposal.",
+ "title": "Proposal Title",
+ "uid": "proposal_title_field_section",
+ "value": "a proposal title single line"
+ }
+ }
+ },
+ "proposal_summary_segment": {
+ "description": "Detailed information about the proposal.",
+ "title": "Proposal Details",
+ "uid": "proposal_details_section",
+ "value": {
+ "proposal_problem": "a\\nmultiline\\nproblem",
+ "proposal_solution": "a\\nmultiline\\nsolution"
+ }
+ },
+ "public_description_segment": {
+ "description": "Detailed public description information.",
+ "title": "Public Description",
+ "uid": "public_description_section",
+ "value": {
+ "topic_1": "topic 1",
+ "topic_2": "topic 2",
+ "topic_3": "topic 3",
+ "topic_4": "topic 4"
+ }
+ }
+}
\ No newline at end of file
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/proposal.F14.schema.json b/docs/src/architecture/08_concepts/document_templates/proposal/proposal.F14.schema.json
new file mode 100644
index 00000000000..8c08aeea95f
--- /dev/null
+++ b/docs/src/architecture/08_concepts/document_templates/proposal/proposal.F14.schema.json
@@ -0,0 +1,402 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Catalyst Fund 14 Base Proposal Template",
+ "description": "A structured template for creating Fund 14 proposals",
+ "type": "object",
+ "properties": {
+ "$schema": "./.schema.json",
+ "template_version": {
+ "type": "object",
+ "properties": {
+ "uid": {
+ "const": "version_section",
+ "description": "Unique identifier for the version."
+ },
+ "title": {
+ "const": "Version",
+ "description": "Title of the version."
+ },
+ "description": {
+ "const": "The version of the schema, formatted as a ULID.",
+ "description": "Description for the version."
+ },
+ "value": {
+ "type": "string",
+ "description": "A unique identifier for the version, formatted as a ULID.",
+ "pattern": "^[0-9A-HJKMNP-TV-Z]{26}$",
+ "default": "01F8MECHZXK8F8D8F8D8F8D8F8"
+ }
+ },
+ "required": ["uid", "title", "description", "value"]
+ },
+ "category_template": {
+ "type": "object",
+ "properties": {
+ "uid": {
+ "const": "category_section",
+ "description": "Unique identifier for the category."
+ },
+ "title": {
+ "const": "Category",
+ "description": "Title of the category."
+ },
+ "description": {
+ "const": "The category to which this template belongs.",
+ "description": "Description for the category."
+ },
+ "value": {
+ "type": "string",
+ "description": "A unique identifier for the category.",
+ "pattern": "^[a-zA-Z0-9_-]+$",
+ "default": "cardano_open_category"
+ }
+ },
+ "required": ["uid", "title", "description", "value"]
+ },
+ "proposal_setup_segment": {
+ "type": "object",
+ "properties": {
+ "uid": {
+ "const": "proposal_setup_section",
+ "description": "Unique identifier for the Proposal Setup Segment."
+ },
+ "title": {
+ "const": "Proposal Setup",
+ "description": "Title of the Proposal Setup Segment."
+ },
+ "description": {
+ "const": "Basic information about your proposal.",
+ "description": "Description for the Proposal Setup Segment."
+ },
+ "value": {
+ "type": "object",
+ "properties": {
+ "proposal_title": {
+ "type": "object",
+ "properties": {
+ "uid": {
+ "const": "proposal_title_field_section",
+ "description": "Unique identifier for the Proposal Title field."
+ },
+ "title": {
+ "const": "Proposal Title",
+ "description": "Title of the Proposal Title field."
+ },
+ "description": {
+ "const": "The name of the proposal.",
+ "description": "Description for the Proposal Title field."
+ },
+ "value": {
+ "type": "string",
+ "maxLength": 60,
+ "description": "User-provided proposal title.",
+ "format": "string",
+ "pattern": "^[a-zA-Z0-9 ]+$"
+ }
+ },
+ "required": ["uid", "title", "description", "value"]
+ }
+ }
+ }
+ },
+ "required": ["uid", "title", "description", "value"]
+ },
+ "proposal_summary_segment": {
+ "type": "object",
+ "properties": {
+ "uid": {
+ "const": "proposal_details_section",
+ "description": "Unique identifier for the Proposal Details."
+ },
+ "title": {
+ "const": "Proposal Details",
+ "description": "Details about the proposal."
+ },
+ "description": {
+ "const": "Detailed information about the proposal.",
+ "description": "Description for the Proposal Details."
+ },
+ "value": {
+ "type": "object",
+ "properties": {
+ "proposal_problem": {
+ "type": "string",
+ "description": "Describe the problem you're addressing in the Cardano ecosystem.",
+ "maxLength": 1000,
+ "format": "string",
+ "pattern": "^[\\s\\S]*$"
+ },
+ "proposal_solution": {
+ "type": "string",
+ "description": "Describe your solution and how it addresses the problem.",
+ "maxLength": 2000,
+ "format": "string",
+ "pattern": "^[\\s\\S]*$"
+ }
+ },
+ "required": ["proposal_problem", "proposal_solution"]
+ }
+ },
+ "required": ["uid", "title", "description", "value"]
+ },
+ "public_description_segment": {
+ "type": "object",
+ "properties": {
+ "uid": {
+ "const": "public_description_section",
+ "description": "Unique identifier for the Public Description Segment."
+ },
+ "title": {
+ "const": "Public Description",
+ "description": "Public description of the proposal."
+ },
+ "description": {
+ "const": "Detailed public description information.",
+ "description": "Description for the Public Description Segment."
+ },
+ "value": {
+ "type": "object",
+ "properties": {
+ "topic_1": {
+ "type": "string",
+ "description": "First topic of the public description.",
+ "maxLength": 500,
+ "format": "string",
+ "pattern": "^[a-zA-Z0-9 ]+$"
+ },
+ "topic_2": {
+ "type": "string",
+ "description": "Second topic of the public description.",
+ "maxLength": 500,
+ "format": "string",
+ "pattern": "^[a-zA-Z0-9 ]+$"
+ },
+ "topic_3": {
+ "type": "string",
+ "description": "Third topic of the public description.",
+ "maxLength": 500,
+ "format": "string",
+ "pattern": "^[a-zA-Z0-9 ]+$"
+ },
+ "topic_4": {
+ "type": "string",
+ "description": "Fourth topic of the public description.",
+ "maxLength": 500,
+ "format": "string",
+ "pattern": "^[a-zA-Z0-9 ]+$"
+ }
+ },
+ "required": ["topic_1", "topic_2", "topic_3", "topic_4"]
+ }
+ },
+ "required": ["uid", "title", "description", "value"]
+ },
+ "category_segment": {
+ "type": "object",
+ "properties": {
+ "uid": {
+ "const": "category_segment_section",
+ "description": "Unique identifier for the Category Segment."
+ },
+ "title": {
+ "const": "Category Segment",
+ "description": "Segment for categorizing the proposal."
+ },
+ "description": {
+ "const": "Details about the categories related to the proposal.",
+ "description": "Description for the Category Segment."
+ },
+ "value": {
+ "type": "object",
+ "properties": {
+ "additional_questions": {
+ "type": "object",
+ "properties": {
+ "uid": {
+ "const": "additional_questions_section",
+ "description": "Unique identifier for Additional Questions."
+ },
+ "title": {
+ "const": "Additional Questions",
+ "description": "Questions related to the project."
+ },
+ "description": {
+ "const": "Details about additional questions regarding the project.",
+ "description": "Description for Additional Questions."
+ },
+ "value": {
+ "type": "object",
+ "properties": {
+ "is_open_source": {
+ "type": "boolean",
+ "description": "Is the project open source?"
+ },
+ "license_type": {
+ "type": "string",
+ "description": "Type of license used.",
+ "format": "string",
+ "pattern": "^[a-zA-Z0-9 ]+$"
+ },
+ "product_repository_url": {
+ "type": "string",
+ "format": "uri",
+ "description": "URL to the product repository."
+ },
+ "project_documentation_url": {
+ "type": "string",
+ "format": "uri",
+ "description": "URL to project documentation."
+ }
+ },
+ "required": ["is_open_source", "license_type", "product_repository_url", "project_documentation_url"]
+ }
+ },
+ "required": ["uid", "title", "description", "value"]
+ },
+ "milestones": {
+ "type": "object",
+ "properties": {
+ "uid": {
+ "const": "milestones_section",
+ "description": "Unique identifier for the Project Milestones."
+ },
+ "title": {
+ "const": "Project Milestones",
+ "description": "Milestones for the project."
+ },
+ "description": {
+ "const": "Milestones to track project progress.",
+ "description": "Description for the Project Milestones."
+ },
+ "value": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "title": {
+ "type": "string",
+ "description": "Milestone Title.",
+ "maxLength": 100,
+ "format": "string",
+ "pattern": "^[a-zA-Z0-9 ]+$"
+ },
+ "description": {
+ "type": "string",
+ "description": "Milestone Description.",
+ "maxLength": 500,
+ "format": "string",
+ "pattern": "^[\\s\\S]*$"
+ },
+ "deliverables": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "format": "string",
+ "pattern": "^[a-zA-Z0-9 ]+$"
+ }
+ }
+ },
+ "required": ["title", "description", "deliverables"]
+ }
+ }
+ },
+ "required": ["uid", "title", "description", "value"]
+ },
+ "resources": {
+ "type": "object",
+ "properties": {
+ "uid": {
+ "const": "resources_section",
+ "description": "Unique identifier for Resources and Budget."
+ },
+ "title": {
+ "const": "Resources and Budget",
+ "description": "Details about resources and budget."
+ },
+ "description": {
+ "const": "Information about resources and budget allocation.",
+ "description": "Description for Resources and Budget."
+ },
+ "value": {
+ "type": "object",
+ "properties": {
+ "project_team": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "role": {
+ "type": "string",
+ "description": "Role of the team member.",
+ "maxLength": 100,
+ "format": "string",
+ "pattern": "^[a-zA-Z0-9 ]+$"
+ },
+ "experience": {
+ "type": "string",
+ "description": "Relevant experience of the team member.",
+ "maxLength": 500,
+ "format": "string",
+ "pattern": "^[\\s\\S]*$"
+ }
+ },
+ "required": ["role", "experience"]
+ }
+ },
+ "budget_breakdown": {
+ "type": "string",
+ "description": "Detailed breakdown of how the funds will be used.",
+ "maxLength": 2000,
+ "format": "string",
+ "pattern": "^[\\s\\S]*$"
+ }
+ },
+ "required": ["project_team", "budget_breakdown"]
+ }
+ },
+ "required": ["uid", "title", "description", "value"]
+ },
+ "agreements": {
+ "type": "object",
+ "properties": {
+ "uid": {
+ "const": "agreements_section",
+ "description": "Unique identifier for Terms and Agreements."
+ },
+ "title": {
+ "const": "Terms and Agreements",
+ "description": "Agreements related to the proposal."
+ },
+ "description": {
+ "const": "Terms and agreements for the proposal.",
+ "description": "Description for Terms and Agreements."
+ },
+ "value": {
+ "type": "object",
+ "properties": {
+ "agree_fund_rules": {
+ "type": "boolean",
+ "description": "Agreement to fund rules."
+ },
+ "catalyst_terms_and_conditions": {
+ "type": "boolean",
+ "description": "Agreement to terms and conditions."
+ },
+ "privacy_policy": {
+ "type": "boolean",
+ "description": "Agreement to privacy policy."
+ }
+ },
+ "required": ["agree_fund_rules", "catalyst_terms_and_conditions", "privacy_policy"]
+ }
+ },
+ "required": ["uid", "title", "description", "value"]
+ }
+ },
+ "required": ["additional_questions", "milestones", "resources", "agreements"]
+ }
+ },
+ "required": ["uid", "title", "description", "value"]
+ }
+ }
+}
\ No newline at end of file
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/proposalTemplate.F14.schema.json b/docs/src/architecture/08_concepts/document_templates/proposal/proposalTemplate.F14.schema.json
new file mode 100644
index 00000000000..8583da87505
--- /dev/null
+++ b/docs/src/architecture/08_concepts/document_templates/proposal/proposalTemplate.F14.schema.json
@@ -0,0 +1,401 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Catalyst Fund 14 Base Proposal Template",
+ "description": "A structured template for creating Fund 14 proposals",
+ "type": "object",
+ "properties": {
+ "template_version": {
+ "type": "object",
+ "properties": {
+ "uid": {
+ "const": "version_section",
+ "description": "Unique identifier for the version."
+ },
+ "title": {
+ "const": "Version",
+ "description": "Title of the version."
+ },
+ "description": {
+ "const": "The version of the schema, formatted as a ULID.",
+ "description": "Description for the version."
+ },
+ "value": {
+ "type": "string",
+ "description": "A unique identifier for the version, formatted as a ULID.",
+ "pattern": "^[0-9A-HJKMNP-TV-Z]{26}$",
+ "default": "01F8MECHZXK8F8D8F8D8F8D8F8"
+ }
+ },
+ "required": ["uid", "title", "description", "value"]
+ },
+ "category_template": {
+ "type": "object",
+ "properties": {
+ "uid": {
+ "const": "category_section",
+ "description": "Unique identifier for the category."
+ },
+ "title": {
+ "const": "Category",
+ "description": "Title of the category."
+ },
+ "description": {
+ "const": "The category to which this template belongs.",
+ "description": "Description for the category."
+ },
+ "value": {
+ "type": "string",
+ "description": "A unique identifier for the category.",
+ "pattern": "^[a-zA-Z0-9_-]+$",
+ "default": "cardano_open_category"
+ }
+ },
+ "required": ["uid", "title", "description", "value"]
+ },
+ "proposal_setup_segment": {
+ "type": "object",
+ "properties": {
+ "uid": {
+ "const": "proposal_setup_section",
+ "description": "Unique identifier for the Proposal Setup Segment."
+ },
+ "title": {
+ "const": "Proposal Setup",
+ "description": "Title of the Proposal Setup Segment."
+ },
+ "description": {
+ "const": "Basic information about your proposal.",
+ "description": "Description for the Proposal Setup Segment."
+ },
+ "value": {
+ "type": "object",
+ "properties": {
+ "proposal_title": {
+ "type": "object",
+ "properties": {
+ "uid": {
+ "const": "proposal_title_field_section",
+ "description": "Unique identifier for the Proposal Title field."
+ },
+ "title": {
+ "const": "Proposal Title",
+ "description": "Title of the Proposal Title field."
+ },
+ "description": {
+ "const": "The name of the proposal.",
+ "description": "Description for the Proposal Title field."
+ },
+ "value": {
+ "type": "string",
+ "maxLength": 60,
+ "description": "User-provided proposal title.",
+ "format": "string",
+ "pattern": "^[a-zA-Z0-9 ]+$"
+ }
+ },
+ "required": ["uid", "title", "description", "value"]
+ }
+ }
+ }
+ },
+ "required": ["uid", "title", "description", "value"]
+ },
+ "proposal_summary_segment": {
+ "type": "object",
+ "properties": {
+ "uid": {
+ "const": "proposal_details_section",
+ "description": "Unique identifier for the Proposal Details."
+ },
+ "title": {
+ "const": "Proposal Details",
+ "description": "Details about the proposal."
+ },
+ "description": {
+ "const": "Detailed information about the proposal.",
+ "description": "Description for the Proposal Details."
+ },
+ "value": {
+ "type": "object",
+ "properties": {
+ "proposal_problem": {
+ "type": "string",
+ "description": "Describe the problem you're addressing in the Cardano ecosystem.",
+ "maxLength": 1000,
+ "format": "string",
+ "pattern": "^[\\s\\S]*$"
+ },
+ "proposal_solution": {
+ "type": "string",
+ "description": "Describe your solution and how it addresses the problem.",
+ "maxLength": 2000,
+ "format": "string",
+ "pattern": "^[\\s\\S]*$"
+ }
+ },
+ "required": ["proposal_problem", "proposal_solution"]
+ }
+ },
+ "required": ["uid", "title", "description", "value"]
+ },
+ "public_description_segment": {
+ "type": "object",
+ "properties": {
+ "uid": {
+ "const": "public_description_section",
+ "description": "Unique identifier for the Public Description Segment."
+ },
+ "title": {
+ "const": "Public Description",
+ "description": "Public description of the proposal."
+ },
+ "description": {
+ "const": "Detailed public description information.",
+ "description": "Description for the Public Description Segment."
+ },
+ "value": {
+ "type": "object",
+ "properties": {
+ "topic_1": {
+ "type": "string",
+ "description": "First topic of the public description.",
+ "maxLength": 500,
+ "format": "string",
+ "pattern": "^[a-zA-Z0-9 ]+$"
+ },
+ "topic_2": {
+ "type": "string",
+ "description": "Second topic of the public description.",
+ "maxLength": 500,
+ "format": "string",
+ "pattern": "^[a-zA-Z0-9 ]+$"
+ },
+ "topic_3": {
+ "type": "string",
+ "description": "Third topic of the public description.",
+ "maxLength": 500,
+ "format": "string",
+ "pattern": "^[a-zA-Z0-9 ]+$"
+ },
+ "topic_4": {
+ "type": "string",
+ "description": "Fourth topic of the public description.",
+ "maxLength": 500,
+ "format": "string",
+ "pattern": "^[a-zA-Z0-9 ]+$"
+ }
+ },
+ "required": ["topic_1", "topic_2", "topic_3", "topic_4"]
+ }
+ },
+ "required": ["uid", "title", "description", "value"]
+ },
+ "category_segment": {
+ "type": "object",
+ "properties": {
+ "uid": {
+ "const": "category_segment_section",
+ "description": "Unique identifier for the Category Segment."
+ },
+ "title": {
+ "const": "Category Segment",
+ "description": "Segment for categorizing the proposal."
+ },
+ "description": {
+ "const": "Details about the categories related to the proposal.",
+ "description": "Description for the Category Segment."
+ },
+ "value": {
+ "type": "object",
+ "properties": {
+ "additional_questions": {
+ "type": "object",
+ "properties": {
+ "uid": {
+ "const": "additional_questions_section",
+ "description": "Unique identifier for Additional Questions."
+ },
+ "title": {
+ "const": "Additional Questions",
+ "description": "Questions related to the project."
+ },
+ "description": {
+ "const": "Details about additional questions regarding the project.",
+ "description": "Description for Additional Questions."
+ },
+ "value": {
+ "type": "object",
+ "properties": {
+ "is_open_source": {
+ "type": "boolean",
+ "description": "Is the project open source?"
+ },
+ "license_type": {
+ "type": "string",
+ "description": "Type of license used.",
+ "format": "string",
+ "pattern": "^[a-zA-Z0-9 ]+$"
+ },
+ "product_repository_url": {
+ "type": "string",
+ "format": "uri",
+ "description": "URL to the product repository."
+ },
+ "project_documentation_url": {
+ "type": "string",
+ "format": "uri",
+ "description": "URL to project documentation."
+ }
+ },
+ "required": ["is_open_source", "license_type", "product_repository_url", "project_documentation_url"]
+ }
+ },
+ "required": ["uid", "title", "description", "value"]
+ },
+ "milestones": {
+ "type": "object",
+ "properties": {
+ "uid": {
+ "const": "milestones_section",
+ "description": "Unique identifier for the Project Milestones."
+ },
+ "title": {
+ "const": "Project Milestones",
+ "description": "Milestones for the project."
+ },
+ "description": {
+ "const": "Milestones to track project progress.",
+ "description": "Description for the Project Milestones."
+ },
+ "value": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "title": {
+ "type": "string",
+ "description": "Milestone Title.",
+ "maxLength": 100,
+ "format": "string",
+ "pattern": "^[a-zA-Z0-9 ]+$"
+ },
+ "description": {
+ "type": "string",
+ "description": "Milestone Description.",
+ "maxLength": 500,
+ "format": "string",
+ "pattern": "^[\\s\\S]*$"
+ },
+ "deliverables": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "format": "string",
+ "pattern": "^[a-zA-Z0-9 ]+$"
+ }
+ }
+ },
+ "required": ["title", "description", "deliverables"]
+ }
+ }
+ },
+ "required": ["uid", "title", "description", "value"]
+ },
+ "resources": {
+ "type": "object",
+ "properties": {
+ "uid": {
+ "const": "resources_section",
+ "description": "Unique identifier for Resources and Budget."
+ },
+ "title": {
+ "const": "Resources and Budget",
+ "description": "Details about resources and budget."
+ },
+ "description": {
+ "const": "Information about resources and budget allocation.",
+ "description": "Description for Resources and Budget."
+ },
+ "value": {
+ "type": "object",
+ "properties": {
+ "project_team": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "role": {
+ "type": "string",
+ "description": "Role of the team member.",
+ "maxLength": 100,
+ "format": "string",
+ "pattern": "^[a-zA-Z0-9 ]+$"
+ },
+ "experience": {
+ "type": "string",
+ "description": "Relevant experience of the team member.",
+ "maxLength": 500,
+ "format": "string",
+ "pattern": "^[\\s\\S]*$"
+ }
+ },
+ "required": ["role", "experience"]
+ }
+ },
+ "budget_breakdown": {
+ "type": "string",
+ "description": "Detailed breakdown of how the funds will be used.",
+ "maxLength": 2000,
+ "format": "string",
+ "pattern": "^[\\s\\S]*$"
+ }
+ },
+ "required": ["project_team", "budget_breakdown"]
+ }
+ },
+ "required": ["uid", "title", "description", "value"]
+ },
+ "agreements": {
+ "type": "object",
+ "properties": {
+ "uid": {
+ "const": "agreements_section",
+ "description": "Unique identifier for Terms and Agreements."
+ },
+ "title": {
+ "const": "Terms and Agreements",
+ "description": "Agreements related to the proposal."
+ },
+ "description": {
+ "const": "Terms and agreements for the proposal.",
+ "description": "Description for Terms and Agreements."
+ },
+ "value": {
+ "type": "object",
+ "properties": {
+ "agree_fund_rules": {
+ "type": "boolean",
+ "description": "Agreement to fund rules."
+ },
+ "catalyst_terms_and_conditions": {
+ "type": "boolean",
+ "description": "Agreement to terms and conditions."
+ },
+ "privacy_policy": {
+ "type": "boolean",
+ "description": "Agreement to privacy policy."
+ }
+ },
+ "required": ["agree_fund_rules", "catalyst_terms_and_conditions", "privacy_policy"]
+ }
+ },
+ "required": ["uid", "title", "description", "value"]
+ }
+ },
+ "required": ["additional_questions", "milestones", "resources", "agreements"]
+ }
+ },
+ "required": ["uid", "title", "description", "value"]
+ }
+ }
+}
\ No newline at end of file
From 0b447045aa4814f4780439df338bec173d7b33ec Mon Sep 17 00:00:00 2001
From: Steven Johnson
Date: Wed, 4 Dec 2024 23:19:05 +0700
Subject: [PATCH 02/25] feat(cat-gateway): wip f14 templates
---
...38-9258-4fbc-a62e-7faa6e58318f.schema.json | 255 +++++++++++
.../F14-Generic/proposal.F14.example.json | 19 +
.../proposal/proposal.F14.schema.json | 402 ------------------
...json => proposalTemplate.F14.example.json} | 0
4 files changed, 274 insertions(+), 402 deletions(-)
create mode 100644 docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
create mode 100644 docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/proposal.F14.example.json
delete mode 100644 docs/src/architecture/08_concepts/document_templates/proposal/proposal.F14.schema.json
rename docs/src/architecture/08_concepts/document_templates/proposal/{proposal.F14.example.json => proposalTemplate.F14.example.json} (100%)
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
new file mode 100644
index 00000000000..07bcf365c27
--- /dev/null
+++ b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
@@ -0,0 +1,255 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Catalyst Fund 14 Base Proposal Template",
+ "description": "A structured template for creating Fund 14 proposals",
+ "type": "object",
+ "properties": {
+ "$schema": {
+ "type": "string",
+ "format": "path",
+ "const": "./0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json",
+ "readOnly": true
+ },
+ "general": {
+ "type": "object",
+ "properties": {
+ "title": {
+ "type": "string",
+ "title": "Proposal title",
+ "description": "Please note we suggest you use no more than 60 characters for your proposal title so that it can be easily viewed in the voting app.
The title should clearly express what the proposal is about. Voters can see the title in the voting app, even without opening the proposal, so a clear, unambiguous, and concise title is very important.
",
+ "contentMediaType": "text/plain",
+ "pattern": "^.*$",
+ "maxLength": 80,
+ "minLength": 0
+ },
+ {
+ "email": {
+ "type": "string",
+ "title": "Email",
+ "description": "Please provide the name and surname of the main applicant. The main applicant is considered as the individual responsible for the project and the person authorized to act on behalf of other applicants (where applicable).
",
+ "contentMediaType": "text/plain",
+ "format": "email",
+ "pattern": "^.*$",
+ "maxLength": 80,
+ "minLength": 0
+ },
+
+ },
+ "applicant": {
+ "type": "string",
+ "title": "Name and surname of main applicant",
+ "description": "Please provide the name and surname of the main applicant. The main applicant is considered as the individual responsible for the project and the person authorized to act on behalf of other applicants (where applicable).
",
+ "contentMediaType": "text/plain",
+ "pattern": "^.*$",
+ "maxLength": 80,
+ "minLength": 0
+ },
+ "applicant_type": {
+ "type": "string",
+ "title": "Are you delivering this project as an individual or as an entity (whether formally incorporated or not)",
+ "description": "Please select from one of the following:
",
+ "contentMediaType": "text/plain",
+ "enum": [
+ "Individual",
+ "Entity (Incorporated)",
+ "Entity (Not Incorporated)"
+ ],
+ "default": "Individual"
+ },
+ "co-proposers": {
+ "type": "string",
+ "title": "Co-proposers and additional applicants",
+ "description": "List any persons who are submitting the proposal jointly with the main applicant. Make sure you have confirmed approval/awareness with these individuals / accounts before adding them. If there is more than one proposer, identify the lead person who is authorized to act on behalf of other co-proposers.
IMPORTANT - A maximum of 6 (six) proposals can be led or co-proposed by the same applicant or enterprise. Please, reference Fund13 rules for added detail.
",
+ "contentMediaType": "text/plain",
+ "pattern": "^[\\S\\s]$",
+ "maxLength": 1024,
+ "minLength": 0
+ },
+ "requested_funds": {
+ "type": "integer",
+ "title": "Requested funds in ada",
+ "description": "There is a minimum and a maximum amount of funding that can be requested in a single Catalyst proposal. These are outlined below per each category:
Minimum Funding Amount per proposal:
- Cardano Open: ₳15,000
- Cardano Uses Cases: ₳15,000
- Cardano Partners: ₳500,000
Maximum Funding Amount per proposal:
- Cardano Open:
- Developers (technical): ₳200,000
- Ecosystem (non-technical): ₳100,000
- Cardano Uses Cases:
- Concept: ₳150,000
- Product: ₳500,000
- Cardano Partners:
- Enterprise R&D: ₳2,000,000
- Growth & Acceleration: ₳2,000,000
",
+ "minimum": 1,
+ "maximum": 18446744073709551615,
+ "format": "cardano:ada"
+ },
+ "duration": {
+ "type": "integer",
+ "title": "Please specify how many months you expect your project to last (from 2-12 months)",
+ "description": "Minimum 2 months - Maximum 12 months.
The scope of your funding request and this project is expected to produce the deliverables you specify in the proposal within 2-12 months.
If you believe your project will take longer than 12 months, consider reducing the project’s scope so that it becomes achievable within 12 months.
If your project completes earlier than scheduled so long as you have submitted your PoAs and Project Close-out report and video then your project can be closed out.
",
+ "minimum": 2,
+ "maximum": 12,
+ "format": "datetime:months"
+ },
+ "translated": {
+ "type": "boolean",
+ "title": "Please indicate if your proposal has been auto-translated into English from another language",
+ "description": "YES/NO - Tick YES so readers are reminded that your proposal has been translated, and that they should be tolerant of any language imperfections.
You can either link a document with your proposal in its original language OR provide your response in your native language after the English language in each question if you wish.
Tick NO if your proposal has not been auto-translated into English from another language.
",
+ "format": "yes/no"
+ },
+ "problem": {
+ "type": "string",
+ "title": "What is the problem you want to solve? (200-character limit including spaces)",
+ "description": "Ensure you present a well-defined problem. What is the core issue that you hope to fix? Remember: the reader might not recognize the problem unless you state it clearly.
This answer will be displayed on the Catalyst voting app, so voters will see it even if they don't open your proposal to read it in detail.
",
+ "contentMediaType": "text/plain",
+ "pattern": "^[\\S\\s]$",
+ "maxLength": 200,
+ "minLength": 1
+ },
+ "solution": {
+ "type": "string",
+ "title": "Summarize your solution to the problem (200-character limit including spaces)",
+ "description": "Focus on what you are going to do, or make, or change, to solve the problem. So not 'There should be a way to....' but 'We will make a...'
Clearly state how the solution addresses the specific problem you have identified - connect the 'why' and the 'how'.
This answer will be displayed on the Catalyst voting app, so voters will see it even if they do not open your proposal and read it in detail.
",
+ "contentMediaType": "text/plain",
+ "pattern": "^[\\S\\s]$",
+ "maxLength": 200,
+ "minLength": 1
+ },
+ "links": {
+ "type": "array",
+ "title": "Website / GitHub repository, White paper, Marketing or any other relevant link",
+ "description": "Here, provide links to yours or your partner organization’s website, repository, or marketing. Alternatively, provide links to any whitepaper or other publication relevant to your proposal.
Note however that this is extra information that voters and Community Reviewers might choose not to read. You should not fail to include any of the questions in this form because you feel the answers can be found elsewhere.
If any links are specified make sure these are added in good order (first link must be present before specifying second). Also ensure all links include ‘https’. Without these steps, the form will not be submittable and show errors.
",
+ "items": {
+ "type": "string",
+ "format": "uri",
+ "contentMediaType": "text/plain",
+ "maxLength": 1024
+ },
+ "uniqueItems": true,
+ "default": [],
+ "minItems": 0,
+ "maxItems": 3
+ },
+ "dependencies": {
+ "type": "string",
+ "title": "If you have any dependencies then, please describe what the dependency is and why you believe it is essential for your project’s delivery. If NO, please write “No dependencies.”",
+ "description": "Here you should list any dependencies and prerequisites for your project’s success. These are usually external factors (such as third-party suppliers, external resources, third-party software, etc.) that may cause a delay, since a project has less control over them. In case of third party software, indicate whether you have the necessary licenses and permission to use such software.
",
+ "contentMediaType": "text/plain",
+ "pattern": "^[\\S\\s]$",
+ "maxLength": 1024,
+ "minLength": 0
+ },
+ "open_source": {
+ "type": "boolean",
+ "title": "Will your project’s output/s be fully open source?",
+ "description": "Open source refers to something people can modify and share because its design is publicly accessible.
Open source software is software with source code that anyone can inspect, modify, and enhance. Conversely, only the original authors of proprietary software can legally copy, inspect, and alter that software.
",
+ "format": "yes/no"
+ },
+ "license_info": {
+ "type": "string",
+ "title": "[GENERAL] Please provide here more information on the open source status of your project outputs",
+ "description": "If you answered YES to the above question:
If declaring the project is open source in the application form, the project should be open source-available throughout the entire lifecycle of the project with a declared open-source repository.
Please indicate here the type of license you intend to use for open source and provide any further information you feel is relevant to the open source status of your project outputs.
If only certain elements of your code will be open source please clarify which elements will be open source here.
If you answered NO to the above question, please give further details as to why your projects outputs will not be open source.
",
+ "contentMediaType": "text/plain",
+ "pattern": "^[\\S\\s]$",
+ "maxLength": 1024,
+ "minLength": 0
+ }
+ },
+ "required": [
+ "title",
+ "applicant",
+ "applicant_type",
+ "requested_funds",
+ "duration",
+ "translated",
+ "problem",
+ "solution",
+ "open_source",
+ "license_info"
+ ]
+ },
+ "metadata": {
+ "title": "Horizons",
+ "description": "Please choose the most relevant category group and tag related to the outcomes of your proposal. Can select only one group and one tag.
",
+ "format": "nested-tag-selector",
+ "oneOf": [
+ {
+ "type": "object",
+ "properties": {
+ "group": {
+ "type": "string",
+ "const": "Governance"
+ },
+ "tag": {
+ "type": "string",
+ "enum": [
+ "Governance",
+ "DAO"
+ ]
+ }
+ }
+ },
+ {
+ "type": "object",
+ "properties": {
+ "group": {
+ "type": "string",
+ "const": "Education"
+ },
+ "tag": {
+ "type": "string",
+ "enum": [
+ "Education",
+ "Learn to Earn",
+ "Training",
+ "Translation"
+ ]
+ }
+ }
+ },
+ {
+ "group": {
+ "type": "string",
+ "const": "Community & Outreach"
+ },
+ "tag": {
+ "type": "string",
+ "enum": [
+ "Connected Community",
+ "Community",
+ "Community Outreach",
+ "Social Media"
+ ]
+ }
+ },
+ {
+ "group": {
+ "type": "string",
+ "const": "Development & Tools"
+ },
+ "tag": {
+ "type": "string",
+ "enum": [
+ "Developer Tools",
+ "L2",
+ "Infrastructure",
+ "Analytics",
+ "AI",
+ "Research",
+ "UTXO",
+ "P2P"
+ ]
+ }
+ }
+ ]
+ },
+ "agreements": {
+ "type": "object",
+ "properties": {
+ "fund_rules": {
+ "type": "string",
+ "title": "Fund Rules:",
+ "description": "By submitting a proposal to Project Catalyst Fund13, I confirm that I have read and agree to be bound by the Fund Rules.
",
+ "contentMediaType": "text/plain",
+ "enum": [
+ "Yes",
+ "No"
+ ],
+ "default": "No",
+ "pattern": "Yes",
+ "format": "checkbox"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/proposal.F14.example.json b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/proposal.F14.example.json
new file mode 100644
index 00000000000..d77c676cb9e
--- /dev/null
+++ b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/proposal.F14.example.json
@@ -0,0 +1,19 @@
+{
+ "$schema": "./0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json",
+ "general": {
+ "title": "Single line plain text ..............................",
+ "links": [
+ "http://notauri",
+ "ftp://some_old_site",
+ "cardano://some-block"
+ ],
+ "applicant_type": "Individual",
+ },
+ "metadata": {
+ "group": "Education",
+ "tag": "Learn to Earn"
+ },
+ "agreements": {
+ "fund_rules": "Yes"
+ }
+}
\ No newline at end of file
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/proposal.F14.schema.json b/docs/src/architecture/08_concepts/document_templates/proposal/proposal.F14.schema.json
deleted file mode 100644
index 8c08aeea95f..00000000000
--- a/docs/src/architecture/08_concepts/document_templates/proposal/proposal.F14.schema.json
+++ /dev/null
@@ -1,402 +0,0 @@
-{
- "$schema": "http://json-schema.org/draft-07/schema#",
- "title": "Catalyst Fund 14 Base Proposal Template",
- "description": "A structured template for creating Fund 14 proposals",
- "type": "object",
- "properties": {
- "$schema": "./.schema.json",
- "template_version": {
- "type": "object",
- "properties": {
- "uid": {
- "const": "version_section",
- "description": "Unique identifier for the version."
- },
- "title": {
- "const": "Version",
- "description": "Title of the version."
- },
- "description": {
- "const": "The version of the schema, formatted as a ULID.",
- "description": "Description for the version."
- },
- "value": {
- "type": "string",
- "description": "A unique identifier for the version, formatted as a ULID.",
- "pattern": "^[0-9A-HJKMNP-TV-Z]{26}$",
- "default": "01F8MECHZXK8F8D8F8D8F8D8F8"
- }
- },
- "required": ["uid", "title", "description", "value"]
- },
- "category_template": {
- "type": "object",
- "properties": {
- "uid": {
- "const": "category_section",
- "description": "Unique identifier for the category."
- },
- "title": {
- "const": "Category",
- "description": "Title of the category."
- },
- "description": {
- "const": "The category to which this template belongs.",
- "description": "Description for the category."
- },
- "value": {
- "type": "string",
- "description": "A unique identifier for the category.",
- "pattern": "^[a-zA-Z0-9_-]+$",
- "default": "cardano_open_category"
- }
- },
- "required": ["uid", "title", "description", "value"]
- },
- "proposal_setup_segment": {
- "type": "object",
- "properties": {
- "uid": {
- "const": "proposal_setup_section",
- "description": "Unique identifier for the Proposal Setup Segment."
- },
- "title": {
- "const": "Proposal Setup",
- "description": "Title of the Proposal Setup Segment."
- },
- "description": {
- "const": "Basic information about your proposal.",
- "description": "Description for the Proposal Setup Segment."
- },
- "value": {
- "type": "object",
- "properties": {
- "proposal_title": {
- "type": "object",
- "properties": {
- "uid": {
- "const": "proposal_title_field_section",
- "description": "Unique identifier for the Proposal Title field."
- },
- "title": {
- "const": "Proposal Title",
- "description": "Title of the Proposal Title field."
- },
- "description": {
- "const": "The name of the proposal.",
- "description": "Description for the Proposal Title field."
- },
- "value": {
- "type": "string",
- "maxLength": 60,
- "description": "User-provided proposal title.",
- "format": "string",
- "pattern": "^[a-zA-Z0-9 ]+$"
- }
- },
- "required": ["uid", "title", "description", "value"]
- }
- }
- }
- },
- "required": ["uid", "title", "description", "value"]
- },
- "proposal_summary_segment": {
- "type": "object",
- "properties": {
- "uid": {
- "const": "proposal_details_section",
- "description": "Unique identifier for the Proposal Details."
- },
- "title": {
- "const": "Proposal Details",
- "description": "Details about the proposal."
- },
- "description": {
- "const": "Detailed information about the proposal.",
- "description": "Description for the Proposal Details."
- },
- "value": {
- "type": "object",
- "properties": {
- "proposal_problem": {
- "type": "string",
- "description": "Describe the problem you're addressing in the Cardano ecosystem.",
- "maxLength": 1000,
- "format": "string",
- "pattern": "^[\\s\\S]*$"
- },
- "proposal_solution": {
- "type": "string",
- "description": "Describe your solution and how it addresses the problem.",
- "maxLength": 2000,
- "format": "string",
- "pattern": "^[\\s\\S]*$"
- }
- },
- "required": ["proposal_problem", "proposal_solution"]
- }
- },
- "required": ["uid", "title", "description", "value"]
- },
- "public_description_segment": {
- "type": "object",
- "properties": {
- "uid": {
- "const": "public_description_section",
- "description": "Unique identifier for the Public Description Segment."
- },
- "title": {
- "const": "Public Description",
- "description": "Public description of the proposal."
- },
- "description": {
- "const": "Detailed public description information.",
- "description": "Description for the Public Description Segment."
- },
- "value": {
- "type": "object",
- "properties": {
- "topic_1": {
- "type": "string",
- "description": "First topic of the public description.",
- "maxLength": 500,
- "format": "string",
- "pattern": "^[a-zA-Z0-9 ]+$"
- },
- "topic_2": {
- "type": "string",
- "description": "Second topic of the public description.",
- "maxLength": 500,
- "format": "string",
- "pattern": "^[a-zA-Z0-9 ]+$"
- },
- "topic_3": {
- "type": "string",
- "description": "Third topic of the public description.",
- "maxLength": 500,
- "format": "string",
- "pattern": "^[a-zA-Z0-9 ]+$"
- },
- "topic_4": {
- "type": "string",
- "description": "Fourth topic of the public description.",
- "maxLength": 500,
- "format": "string",
- "pattern": "^[a-zA-Z0-9 ]+$"
- }
- },
- "required": ["topic_1", "topic_2", "topic_3", "topic_4"]
- }
- },
- "required": ["uid", "title", "description", "value"]
- },
- "category_segment": {
- "type": "object",
- "properties": {
- "uid": {
- "const": "category_segment_section",
- "description": "Unique identifier for the Category Segment."
- },
- "title": {
- "const": "Category Segment",
- "description": "Segment for categorizing the proposal."
- },
- "description": {
- "const": "Details about the categories related to the proposal.",
- "description": "Description for the Category Segment."
- },
- "value": {
- "type": "object",
- "properties": {
- "additional_questions": {
- "type": "object",
- "properties": {
- "uid": {
- "const": "additional_questions_section",
- "description": "Unique identifier for Additional Questions."
- },
- "title": {
- "const": "Additional Questions",
- "description": "Questions related to the project."
- },
- "description": {
- "const": "Details about additional questions regarding the project.",
- "description": "Description for Additional Questions."
- },
- "value": {
- "type": "object",
- "properties": {
- "is_open_source": {
- "type": "boolean",
- "description": "Is the project open source?"
- },
- "license_type": {
- "type": "string",
- "description": "Type of license used.",
- "format": "string",
- "pattern": "^[a-zA-Z0-9 ]+$"
- },
- "product_repository_url": {
- "type": "string",
- "format": "uri",
- "description": "URL to the product repository."
- },
- "project_documentation_url": {
- "type": "string",
- "format": "uri",
- "description": "URL to project documentation."
- }
- },
- "required": ["is_open_source", "license_type", "product_repository_url", "project_documentation_url"]
- }
- },
- "required": ["uid", "title", "description", "value"]
- },
- "milestones": {
- "type": "object",
- "properties": {
- "uid": {
- "const": "milestones_section",
- "description": "Unique identifier for the Project Milestones."
- },
- "title": {
- "const": "Project Milestones",
- "description": "Milestones for the project."
- },
- "description": {
- "const": "Milestones to track project progress.",
- "description": "Description for the Project Milestones."
- },
- "value": {
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "title": {
- "type": "string",
- "description": "Milestone Title.",
- "maxLength": 100,
- "format": "string",
- "pattern": "^[a-zA-Z0-9 ]+$"
- },
- "description": {
- "type": "string",
- "description": "Milestone Description.",
- "maxLength": 500,
- "format": "string",
- "pattern": "^[\\s\\S]*$"
- },
- "deliverables": {
- "type": "array",
- "items": {
- "type": "string",
- "format": "string",
- "pattern": "^[a-zA-Z0-9 ]+$"
- }
- }
- },
- "required": ["title", "description", "deliverables"]
- }
- }
- },
- "required": ["uid", "title", "description", "value"]
- },
- "resources": {
- "type": "object",
- "properties": {
- "uid": {
- "const": "resources_section",
- "description": "Unique identifier for Resources and Budget."
- },
- "title": {
- "const": "Resources and Budget",
- "description": "Details about resources and budget."
- },
- "description": {
- "const": "Information about resources and budget allocation.",
- "description": "Description for Resources and Budget."
- },
- "value": {
- "type": "object",
- "properties": {
- "project_team": {
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "role": {
- "type": "string",
- "description": "Role of the team member.",
- "maxLength": 100,
- "format": "string",
- "pattern": "^[a-zA-Z0-9 ]+$"
- },
- "experience": {
- "type": "string",
- "description": "Relevant experience of the team member.",
- "maxLength": 500,
- "format": "string",
- "pattern": "^[\\s\\S]*$"
- }
- },
- "required": ["role", "experience"]
- }
- },
- "budget_breakdown": {
- "type": "string",
- "description": "Detailed breakdown of how the funds will be used.",
- "maxLength": 2000,
- "format": "string",
- "pattern": "^[\\s\\S]*$"
- }
- },
- "required": ["project_team", "budget_breakdown"]
- }
- },
- "required": ["uid", "title", "description", "value"]
- },
- "agreements": {
- "type": "object",
- "properties": {
- "uid": {
- "const": "agreements_section",
- "description": "Unique identifier for Terms and Agreements."
- },
- "title": {
- "const": "Terms and Agreements",
- "description": "Agreements related to the proposal."
- },
- "description": {
- "const": "Terms and agreements for the proposal.",
- "description": "Description for Terms and Agreements."
- },
- "value": {
- "type": "object",
- "properties": {
- "agree_fund_rules": {
- "type": "boolean",
- "description": "Agreement to fund rules."
- },
- "catalyst_terms_and_conditions": {
- "type": "boolean",
- "description": "Agreement to terms and conditions."
- },
- "privacy_policy": {
- "type": "boolean",
- "description": "Agreement to privacy policy."
- }
- },
- "required": ["agree_fund_rules", "catalyst_terms_and_conditions", "privacy_policy"]
- }
- },
- "required": ["uid", "title", "description", "value"]
- }
- },
- "required": ["additional_questions", "milestones", "resources", "agreements"]
- }
- },
- "required": ["uid", "title", "description", "value"]
- }
- }
-}
\ No newline at end of file
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/proposal.F14.example.json b/docs/src/architecture/08_concepts/document_templates/proposal/proposalTemplate.F14.example.json
similarity index 100%
rename from docs/src/architecture/08_concepts/document_templates/proposal/proposal.F14.example.json
rename to docs/src/architecture/08_concepts/document_templates/proposal/proposalTemplate.F14.example.json
From bb6d8a9cb5bb71c35335b4525cb7da4a88b4eaa8 Mon Sep 17 00:00:00 2001
From: Nathan Bogale
Date: Wed, 4 Dec 2024 21:59:47 +0300
Subject: [PATCH 03/25] feat(cat-gateway): initialization of f14 templates
---
...38-9258-4fbc-a62e-7faa6e58318f.schema.json | 508 +++---
.../proposal.F14.example.json | 0
.../proposalTemplate.F14.example.json | 0
.../proposalTemplate.F14.schema.json | 1514 +++++++++++++++++
.../proposalTemplate.F14.example.json | 105 --
.../proposal/proposalTemplate.F14.schema.json | 401 -----
6 files changed, 1768 insertions(+), 760 deletions(-)
rename docs/src/architecture/08_concepts/document_templates/proposal/{F14-Generic => F14-Generic-Steven}/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json (98%)
rename docs/src/architecture/08_concepts/document_templates/proposal/{F14-Generic => F14-Generic-Steven}/proposal.F14.example.json (100%)
create mode 100644 docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/proposalTemplate.F14.example.json
create mode 100644 docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/proposalTemplate.F14.schema.json
delete mode 100644 docs/src/architecture/08_concepts/document_templates/proposal/proposalTemplate.F14.example.json
delete mode 100644 docs/src/architecture/08_concepts/document_templates/proposal/proposalTemplate.F14.schema.json
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic-Steven/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
similarity index 98%
rename from docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
rename to docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic-Steven/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
index 07bcf365c27..033a6ba2be6 100644
--- a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
+++ b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic-Steven/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
@@ -1,255 +1,255 @@
-{
- "$schema": "http://json-schema.org/draft-07/schema#",
- "title": "Catalyst Fund 14 Base Proposal Template",
- "description": "A structured template for creating Fund 14 proposals",
- "type": "object",
- "properties": {
- "$schema": {
- "type": "string",
- "format": "path",
- "const": "./0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json",
- "readOnly": true
- },
- "general": {
- "type": "object",
- "properties": {
- "title": {
- "type": "string",
- "title": "Proposal title",
- "description": "Please note we suggest you use no more than 60 characters for your proposal title so that it can be easily viewed in the voting app.
The title should clearly express what the proposal is about. Voters can see the title in the voting app, even without opening the proposal, so a clear, unambiguous, and concise title is very important.
",
- "contentMediaType": "text/plain",
- "pattern": "^.*$",
- "maxLength": 80,
- "minLength": 0
- },
- {
- "email": {
- "type": "string",
- "title": "Email",
- "description": "Please provide the name and surname of the main applicant. The main applicant is considered as the individual responsible for the project and the person authorized to act on behalf of other applicants (where applicable).
",
- "contentMediaType": "text/plain",
- "format": "email",
- "pattern": "^.*$",
- "maxLength": 80,
- "minLength": 0
- },
-
- },
- "applicant": {
- "type": "string",
- "title": "Name and surname of main applicant",
- "description": "Please provide the name and surname of the main applicant. The main applicant is considered as the individual responsible for the project and the person authorized to act on behalf of other applicants (where applicable).
",
- "contentMediaType": "text/plain",
- "pattern": "^.*$",
- "maxLength": 80,
- "minLength": 0
- },
- "applicant_type": {
- "type": "string",
- "title": "Are you delivering this project as an individual or as an entity (whether formally incorporated or not)",
- "description": "Please select from one of the following:
",
- "contentMediaType": "text/plain",
- "enum": [
- "Individual",
- "Entity (Incorporated)",
- "Entity (Not Incorporated)"
- ],
- "default": "Individual"
- },
- "co-proposers": {
- "type": "string",
- "title": "Co-proposers and additional applicants",
- "description": "List any persons who are submitting the proposal jointly with the main applicant. Make sure you have confirmed approval/awareness with these individuals / accounts before adding them. If there is more than one proposer, identify the lead person who is authorized to act on behalf of other co-proposers.
IMPORTANT - A maximum of 6 (six) proposals can be led or co-proposed by the same applicant or enterprise. Please, reference Fund13 rules for added detail.
",
- "contentMediaType": "text/plain",
- "pattern": "^[\\S\\s]$",
- "maxLength": 1024,
- "minLength": 0
- },
- "requested_funds": {
- "type": "integer",
- "title": "Requested funds in ada",
- "description": "There is a minimum and a maximum amount of funding that can be requested in a single Catalyst proposal. These are outlined below per each category:
Minimum Funding Amount per proposal:
- Cardano Open: ₳15,000
- Cardano Uses Cases: ₳15,000
- Cardano Partners: ₳500,000
Maximum Funding Amount per proposal:
- Cardano Open:
- Developers (technical): ₳200,000
- Ecosystem (non-technical): ₳100,000
- Cardano Uses Cases:
- Concept: ₳150,000
- Product: ₳500,000
- Cardano Partners:
- Enterprise R&D: ₳2,000,000
- Growth & Acceleration: ₳2,000,000
",
- "minimum": 1,
- "maximum": 18446744073709551615,
- "format": "cardano:ada"
- },
- "duration": {
- "type": "integer",
- "title": "Please specify how many months you expect your project to last (from 2-12 months)",
- "description": "Minimum 2 months - Maximum 12 months.
The scope of your funding request and this project is expected to produce the deliverables you specify in the proposal within 2-12 months.
If you believe your project will take longer than 12 months, consider reducing the project’s scope so that it becomes achievable within 12 months.
If your project completes earlier than scheduled so long as you have submitted your PoAs and Project Close-out report and video then your project can be closed out.
",
- "minimum": 2,
- "maximum": 12,
- "format": "datetime:months"
- },
- "translated": {
- "type": "boolean",
- "title": "Please indicate if your proposal has been auto-translated into English from another language",
- "description": "YES/NO - Tick YES so readers are reminded that your proposal has been translated, and that they should be tolerant of any language imperfections.
You can either link a document with your proposal in its original language OR provide your response in your native language after the English language in each question if you wish.
Tick NO if your proposal has not been auto-translated into English from another language.
",
- "format": "yes/no"
- },
- "problem": {
- "type": "string",
- "title": "What is the problem you want to solve? (200-character limit including spaces)",
- "description": "Ensure you present a well-defined problem. What is the core issue that you hope to fix? Remember: the reader might not recognize the problem unless you state it clearly.
This answer will be displayed on the Catalyst voting app, so voters will see it even if they don't open your proposal to read it in detail.
",
- "contentMediaType": "text/plain",
- "pattern": "^[\\S\\s]$",
- "maxLength": 200,
- "minLength": 1
- },
- "solution": {
- "type": "string",
- "title": "Summarize your solution to the problem (200-character limit including spaces)",
- "description": "Focus on what you are going to do, or make, or change, to solve the problem. So not 'There should be a way to....' but 'We will make a...'
Clearly state how the solution addresses the specific problem you have identified - connect the 'why' and the 'how'.
This answer will be displayed on the Catalyst voting app, so voters will see it even if they do not open your proposal and read it in detail.
",
- "contentMediaType": "text/plain",
- "pattern": "^[\\S\\s]$",
- "maxLength": 200,
- "minLength": 1
- },
- "links": {
- "type": "array",
- "title": "Website / GitHub repository, White paper, Marketing or any other relevant link",
- "description": "Here, provide links to yours or your partner organization’s website, repository, or marketing. Alternatively, provide links to any whitepaper or other publication relevant to your proposal.
Note however that this is extra information that voters and Community Reviewers might choose not to read. You should not fail to include any of the questions in this form because you feel the answers can be found elsewhere.
If any links are specified make sure these are added in good order (first link must be present before specifying second). Also ensure all links include ‘https’. Without these steps, the form will not be submittable and show errors.
",
- "items": {
- "type": "string",
- "format": "uri",
- "contentMediaType": "text/plain",
- "maxLength": 1024
- },
- "uniqueItems": true,
- "default": [],
- "minItems": 0,
- "maxItems": 3
- },
- "dependencies": {
- "type": "string",
- "title": "If you have any dependencies then, please describe what the dependency is and why you believe it is essential for your project’s delivery. If NO, please write “No dependencies.”",
- "description": "Here you should list any dependencies and prerequisites for your project’s success. These are usually external factors (such as third-party suppliers, external resources, third-party software, etc.) that may cause a delay, since a project has less control over them. In case of third party software, indicate whether you have the necessary licenses and permission to use such software.
",
- "contentMediaType": "text/plain",
- "pattern": "^[\\S\\s]$",
- "maxLength": 1024,
- "minLength": 0
- },
- "open_source": {
- "type": "boolean",
- "title": "Will your project’s output/s be fully open source?",
- "description": "Open source refers to something people can modify and share because its design is publicly accessible.
Open source software is software with source code that anyone can inspect, modify, and enhance. Conversely, only the original authors of proprietary software can legally copy, inspect, and alter that software.
",
- "format": "yes/no"
- },
- "license_info": {
- "type": "string",
- "title": "[GENERAL] Please provide here more information on the open source status of your project outputs",
- "description": "If you answered YES to the above question:
If declaring the project is open source in the application form, the project should be open source-available throughout the entire lifecycle of the project with a declared open-source repository.
Please indicate here the type of license you intend to use for open source and provide any further information you feel is relevant to the open source status of your project outputs.
If only certain elements of your code will be open source please clarify which elements will be open source here.
If you answered NO to the above question, please give further details as to why your projects outputs will not be open source.
",
- "contentMediaType": "text/plain",
- "pattern": "^[\\S\\s]$",
- "maxLength": 1024,
- "minLength": 0
- }
- },
- "required": [
- "title",
- "applicant",
- "applicant_type",
- "requested_funds",
- "duration",
- "translated",
- "problem",
- "solution",
- "open_source",
- "license_info"
- ]
- },
- "metadata": {
- "title": "Horizons",
- "description": "Please choose the most relevant category group and tag related to the outcomes of your proposal. Can select only one group and one tag.
",
- "format": "nested-tag-selector",
- "oneOf": [
- {
- "type": "object",
- "properties": {
- "group": {
- "type": "string",
- "const": "Governance"
- },
- "tag": {
- "type": "string",
- "enum": [
- "Governance",
- "DAO"
- ]
- }
- }
- },
- {
- "type": "object",
- "properties": {
- "group": {
- "type": "string",
- "const": "Education"
- },
- "tag": {
- "type": "string",
- "enum": [
- "Education",
- "Learn to Earn",
- "Training",
- "Translation"
- ]
- }
- }
- },
- {
- "group": {
- "type": "string",
- "const": "Community & Outreach"
- },
- "tag": {
- "type": "string",
- "enum": [
- "Connected Community",
- "Community",
- "Community Outreach",
- "Social Media"
- ]
- }
- },
- {
- "group": {
- "type": "string",
- "const": "Development & Tools"
- },
- "tag": {
- "type": "string",
- "enum": [
- "Developer Tools",
- "L2",
- "Infrastructure",
- "Analytics",
- "AI",
- "Research",
- "UTXO",
- "P2P"
- ]
- }
- }
- ]
- },
- "agreements": {
- "type": "object",
- "properties": {
- "fund_rules": {
- "type": "string",
- "title": "Fund Rules:",
- "description": "By submitting a proposal to Project Catalyst Fund13, I confirm that I have read and agree to be bound by the Fund Rules.
",
- "contentMediaType": "text/plain",
- "enum": [
- "Yes",
- "No"
- ],
- "default": "No",
- "pattern": "Yes",
- "format": "checkbox"
- }
- }
- }
- }
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Catalyst Fund 14 Base Proposal Template",
+ "description": "A structured template for creating Fund 14 proposals",
+ "type": "object",
+ "properties": {
+ "$schema": {
+ "type": "string",
+ "format": "path",
+ "const": "./0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json",
+ "readOnly": true
+ },
+ "general": {
+ "type": "object",
+ "properties": {
+ "title": {
+ "type": "string",
+ "title": "Proposal title",
+ "description": "Please note we suggest you use no more than 60 characters for your proposal title so that it can be easily viewed in the voting app.
The title should clearly express what the proposal is about. Voters can see the title in the voting app, even without opening the proposal, so a clear, unambiguous, and concise title is very important.
",
+ "contentMediaType": "text/plain",
+ "pattern": "^.*$",
+ "maxLength": 80,
+ "minLength": 0
+ },
+ {
+ "email": {
+ "type": "string",
+ "title": "Email",
+ "description": "Please provide the name and surname of the main applicant. The main applicant is considered as the individual responsible for the project and the person authorized to act on behalf of other applicants (where applicable).
",
+ "contentMediaType": "text/plain",
+ "format": "email",
+ "pattern": "^.*$",
+ "maxLength": 80,
+ "minLength": 0
+ },
+
+ },
+ "applicant": {
+ "type": "string",
+ "title": "Name and surname of main applicant",
+ "description": "Please provide the name and surname of the main applicant. The main applicant is considered as the individual responsible for the project and the person authorized to act on behalf of other applicants (where applicable).
",
+ "contentMediaType": "text/plain",
+ "pattern": "^.*$",
+ "maxLength": 80,
+ "minLength": 0
+ },
+ "applicant_type": {
+ "type": "string",
+ "title": "Are you delivering this project as an individual or as an entity (whether formally incorporated or not)",
+ "description": "Please select from one of the following:
",
+ "contentMediaType": "text/plain",
+ "enum": [
+ "Individual",
+ "Entity (Incorporated)",
+ "Entity (Not Incorporated)"
+ ],
+ "default": "Individual"
+ },
+ "co-proposers": {
+ "type": "string",
+ "title": "Co-proposers and additional applicants",
+ "description": "List any persons who are submitting the proposal jointly with the main applicant. Make sure you have confirmed approval/awareness with these individuals / accounts before adding them. If there is more than one proposer, identify the lead person who is authorized to act on behalf of other co-proposers.
IMPORTANT - A maximum of 6 (six) proposals can be led or co-proposed by the same applicant or enterprise. Please, reference Fund13 rules for added detail.
",
+ "contentMediaType": "text/plain",
+ "pattern": "^[\\S\\s]$",
+ "maxLength": 1024,
+ "minLength": 0
+ },
+ "requested_funds": {
+ "type": "integer",
+ "title": "Requested funds in ada",
+ "description": "There is a minimum and a maximum amount of funding that can be requested in a single Catalyst proposal. These are outlined below per each category:
Minimum Funding Amount per proposal:
- Cardano Open: ₳15,000
- Cardano Uses Cases: ₳15,000
- Cardano Partners: ₳500,000
Maximum Funding Amount per proposal:
- Cardano Open:
- Developers (technical): ₳200,000
- Ecosystem (non-technical): ₳100,000
- Cardano Uses Cases:
- Concept: ₳150,000
- Product: ₳500,000
- Cardano Partners:
- Enterprise R&D: ₳2,000,000
- Growth & Acceleration: ₳2,000,000
",
+ "minimum": 1,
+ "maximum": 18446744073709551615,
+ "format": "cardano:ada"
+ },
+ "duration": {
+ "type": "integer",
+ "title": "Please specify how many months you expect your project to last (from 2-12 months)",
+ "description": "Minimum 2 months - Maximum 12 months.
The scope of your funding request and this project is expected to produce the deliverables you specify in the proposal within 2-12 months.
If you believe your project will take longer than 12 months, consider reducing the project’s scope so that it becomes achievable within 12 months.
If your project completes earlier than scheduled so long as you have submitted your PoAs and Project Close-out report and video then your project can be closed out.
",
+ "minimum": 2,
+ "maximum": 12,
+ "format": "datetime:months"
+ },
+ "translated": {
+ "type": "boolean",
+ "title": "Please indicate if your proposal has been auto-translated into English from another language",
+ "description": "YES/NO - Tick YES so readers are reminded that your proposal has been translated, and that they should be tolerant of any language imperfections.
You can either link a document with your proposal in its original language OR provide your response in your native language after the English language in each question if you wish.
Tick NO if your proposal has not been auto-translated into English from another language.
",
+ "format": "yes/no"
+ },
+ "problem": {
+ "type": "string",
+ "title": "What is the problem you want to solve? (200-character limit including spaces)",
+ "description": "Ensure you present a well-defined problem. What is the core issue that you hope to fix? Remember: the reader might not recognize the problem unless you state it clearly.
This answer will be displayed on the Catalyst voting app, so voters will see it even if they don't open your proposal to read it in detail.
",
+ "contentMediaType": "text/plain",
+ "pattern": "^[\\S\\s]$",
+ "maxLength": 200,
+ "minLength": 1
+ },
+ "solution": {
+ "type": "string",
+ "title": "Summarize your solution to the problem (200-character limit including spaces)",
+ "description": "Focus on what you are going to do, or make, or change, to solve the problem. So not 'There should be a way to....' but 'We will make a...'
Clearly state how the solution addresses the specific problem you have identified - connect the 'why' and the 'how'.
This answer will be displayed on the Catalyst voting app, so voters will see it even if they do not open your proposal and read it in detail.
",
+ "contentMediaType": "text/plain",
+ "pattern": "^[\\S\\s]$",
+ "maxLength": 200,
+ "minLength": 1
+ },
+ "links": {
+ "type": "array",
+ "title": "Website / GitHub repository, White paper, Marketing or any other relevant link",
+ "description": "Here, provide links to yours or your partner organization’s website, repository, or marketing. Alternatively, provide links to any whitepaper or other publication relevant to your proposal.
Note however that this is extra information that voters and Community Reviewers might choose not to read. You should not fail to include any of the questions in this form because you feel the answers can be found elsewhere.
If any links are specified make sure these are added in good order (first link must be present before specifying second). Also ensure all links include ‘https’. Without these steps, the form will not be submittable and show errors.
",
+ "items": {
+ "type": "string",
+ "format": "uri",
+ "contentMediaType": "text/plain",
+ "maxLength": 1024
+ },
+ "uniqueItems": true,
+ "default": [],
+ "minItems": 0,
+ "maxItems": 3
+ },
+ "dependencies": {
+ "type": "string",
+ "title": "If you have any dependencies then, please describe what the dependency is and why you believe it is essential for your project’s delivery. If NO, please write “No dependencies.”",
+ "description": "Here you should list any dependencies and prerequisites for your project’s success. These are usually external factors (such as third-party suppliers, external resources, third-party software, etc.) that may cause a delay, since a project has less control over them. In case of third party software, indicate whether you have the necessary licenses and permission to use such software.
",
+ "contentMediaType": "text/plain",
+ "pattern": "^[\\S\\s]$",
+ "maxLength": 1024,
+ "minLength": 0
+ },
+ "open_source": {
+ "type": "boolean",
+ "title": "Will your project’s output/s be fully open source?",
+ "description": "Open source refers to something people can modify and share because its design is publicly accessible.
Open source software is software with source code that anyone can inspect, modify, and enhance. Conversely, only the original authors of proprietary software can legally copy, inspect, and alter that software.
",
+ "format": "yes/no"
+ },
+ "license_info": {
+ "type": "string",
+ "title": "[GENERAL] Please provide here more information on the open source status of your project outputs",
+ "description": "If you answered YES to the above question:
If declaring the project is open source in the application form, the project should be open source-available throughout the entire lifecycle of the project with a declared open-source repository.
Please indicate here the type of license you intend to use for open source and provide any further information you feel is relevant to the open source status of your project outputs.
If only certain elements of your code will be open source please clarify which elements will be open source here.
If you answered NO to the above question, please give further details as to why your projects outputs will not be open source.
",
+ "contentMediaType": "text/plain",
+ "pattern": "^[\\S\\s]$",
+ "maxLength": 1024,
+ "minLength": 0
+ }
+ },
+ "required": [
+ "title",
+ "applicant",
+ "applicant_type",
+ "requested_funds",
+ "duration",
+ "translated",
+ "problem",
+ "solution",
+ "open_source",
+ "license_info"
+ ]
+ },
+ "metadata": {
+ "title": "Horizons",
+ "description": "Please choose the most relevant category group and tag related to the outcomes of your proposal. Can select only one group and one tag.
",
+ "format": "nested-tag-selector",
+ "oneOf": [
+ {
+ "type": "object",
+ "properties": {
+ "group": {
+ "type": "string",
+ "const": "Governance"
+ },
+ "tag": {
+ "type": "string",
+ "enum": [
+ "Governance",
+ "DAO"
+ ]
+ }
+ }
+ },
+ {
+ "type": "object",
+ "properties": {
+ "group": {
+ "type": "string",
+ "const": "Education"
+ },
+ "tag": {
+ "type": "string",
+ "enum": [
+ "Education",
+ "Learn to Earn",
+ "Training",
+ "Translation"
+ ]
+ }
+ }
+ },
+ {
+ "group": {
+ "type": "string",
+ "const": "Community & Outreach"
+ },
+ "tag": {
+ "type": "string",
+ "enum": [
+ "Connected Community",
+ "Community",
+ "Community Outreach",
+ "Social Media"
+ ]
+ }
+ },
+ {
+ "group": {
+ "type": "string",
+ "const": "Development & Tools"
+ },
+ "tag": {
+ "type": "string",
+ "enum": [
+ "Developer Tools",
+ "L2",
+ "Infrastructure",
+ "Analytics",
+ "AI",
+ "Research",
+ "UTXO",
+ "P2P"
+ ]
+ }
+ }
+ ]
+ },
+ "agreements": {
+ "type": "object",
+ "properties": {
+ "fund_rules": {
+ "type": "string",
+ "title": "Fund Rules:",
+ "description": "By submitting a proposal to Project Catalyst Fund13, I confirm that I have read and agree to be bound by the Fund Rules.
",
+ "contentMediaType": "text/plain",
+ "enum": [
+ "Yes",
+ "No"
+ ],
+ "default": "No",
+ "pattern": "Yes",
+ "format": "checkbox"
+ }
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/proposal.F14.example.json b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic-Steven/proposal.F14.example.json
similarity index 100%
rename from docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/proposal.F14.example.json
rename to docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic-Steven/proposal.F14.example.json
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/proposalTemplate.F14.example.json b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/proposalTemplate.F14.example.json
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/proposalTemplate.F14.schema.json b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/proposalTemplate.F14.schema.json
new file mode 100644
index 00000000000..40176e7e832
--- /dev/null
+++ b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/proposalTemplate.F14.schema.json
@@ -0,0 +1,1514 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://cardano.org/schemas/catalyst/f14/proposal",
+ "version": "1.0.0",
+ "title": "F14 Submission Form",
+ "description": "Schema for the F14 Catalyst Proposal Submission Form",
+ "type": "object",
+ "properties": {
+ "$schema": {
+ "type": "string",
+ "format": "path",
+ "const": "./proposalTemplate.F14.schema.json",
+ "readOnly": true
+ },
+ "setup": {
+ "type": "object",
+ "title": "proposal setup",
+ "description": "Proposal title",
+ "properties": {
+ "title": {
+ "type": "object",
+ "title": "proposal setup",
+ "description": "Proposal title",
+ "properties": {
+ "title": {
+ "type": "string",
+ "title": "Proposal Title",
+ "description": "A clear, unambiguous, and concise title for your proposal",
+ "minLength": 1,
+ "maxLength": 60,
+ "examples": ["DeFi Integration Platform for Cardano"]
+ }
+ },
+ "additionalProperties": false,
+ "required": [
+ "title"
+ ]
+ },
+ "proposer": {
+ "type": "object",
+ "properties": {
+ "mainApplicant": {
+ "type": "string",
+ "title": "Name and surname of main applicant",
+ "description": "Name and surname of main applicant",
+ "$comment": "Please provide the name and surname of the main applicant. The main applicant is considered as the individual responsible for the project and the person authorized to act on behalf of other applicants (where applicable).",
+ "minLength": 2,
+ "maxLength": 100
+ },
+ "applicant_type": {
+ "type": "string",
+ "title": "Are you delivering this project as an individual or as an entity (whether formally incorporated or not)",
+ "description": "Are you delivering this project as an individual or as an entity (whether formally incorporated or not)",
+ "$comment": "Please select from one of the following: 1. Individual 2. Entity (Incorporated) 3. Entity (Not Incorporated)",
+ "enum": [
+ "Individual",
+ "Entity (Incorporated)",
+ "Entity (Not Incorporated)"
+ ]
+ },
+ "co-proposers": {
+ "type": "string",
+ "title": "Co-proposers and additional applicants",
+ "description": "Co-proposers and additional applicants",
+ "$comment": "List any persons who are submitting the proposal jointly with the main applicant. Make sure you have confirmed approval/awareness with these individuals/accounts before adding them. If there is more than one proposer, identify the lead person who is authorized to act on behalf of other co-proposers. IMPORTANT A maximum of 6 (six) proposals can be led or co-proposed by the same applicant or enterprise. Please, reference Fund 13 rules for added detail.",
+ "items": {
+ "type": "string"
+ },
+ "maxItems": 5
+ }
+ },
+ "required": ["mainApplicant", "applicantType"]
+ }
+ },
+ "required": ["title", "proposer"]
+ },
+ "proposalSummary": {
+ "type": "object",
+ "title": "Proposal Summary",
+ "description": "Key information about your proposal",
+ "properties": {
+ "budget": {
+ "type": "object",
+ "title": "Budget Information",
+ "properties": {
+ "requestedFunds": {
+ "type": "number",
+ "title": "Requested funds in ADA",
+ "description": "The amount of funding requested for your proposal",
+ "minimum": 15000,
+ "maximum": 2000000,
+ "examples": ["There is a minimum and a maximum amount of funding that can be requested in a single Catalyst proposal. These are outlined below per each category: Minimum Funding Amount per proposal: Cardano Open: A15,000 Cardano Uses Cases: A15,000 Cardano Partners: A500,000 Maximum Funding Amount per proposal: Cardano Open: Developers (technical): A200,000 • Ecosystem (non-technical): A100,000 Cardano Uses Cases: Concept A150,000 Product: A500,000 Cardano Partners: Enterprise R&D A2,000,000 Growth & Acceleration: A2,000,000"],
+ "format": "cardano:ada",
+ "errorMessage": {
+ "minimum": "Minimum funding amount is 15,000 ADA",
+ "maximum": "Maximum funding amount is 2,000,000 ADA"
+ }
+ }
+ }
+ },
+ "Time": {
+ "type": "object",
+ "properties": {
+ "project_duration": {
+ "type": "integer",
+ "title": "Project Duration in Months",
+ "description": "Specify the expected duration of your project. Projects must be completable within 2-12 months.",
+ "minimum": 2,
+ "maximum": 12,
+ "examples": ["Minimum 2 months-Maximum 12 months. The scope of your funding request and this project is expected to produce the deliverables you specify in the proposal within 2-12 months If you believe your project will take longer than 12 months, consider reducing the project's scope so that it becomes achievable within 12 months If your project completes earlier than scheduled so long as you have submitted your PoAs and Project Close-out report and video then your project can be closed out."]
+ }
+ },
+ "required": ["project_duration"]
+ },
+ "Translation": {
+ "type": "object",
+ "title": "Translation Information",
+ "description": "Information about the proposal's language and translation status",
+ "properties": {
+ "isTranslated": {
+ "type": "boolean",
+ "title": "Auto-translated Status",
+ "description": "Indicate if your proposal has been auto-translated into English from another language",
+ "default": false
+ },
+ "originalLanguage": {
+ "type": "string",
+ "title": "Original Language",
+ "description": "If auto-translated, specify the original language of your proposal",
+ "minLength": 2,
+ "maxLength": 50,
+ "examples": ["Spanish", "Japanese", "French"]
+ },
+ "translationNotes": {
+ "type": "string",
+ "title": "Translation Notes",
+ "description": "Additional notes about the translation or original language content",
+ "maxLength": 500
+ }
+ },
+ "required": ["isTranslated"],
+ "dependencies": {
+ "originalLanguage": ["isTranslated"],
+ "translationNotes": ["isTranslated"]
+ },
+ "if": {
+ "properties": { "isTranslated": { "const": true } }
+ },
+ "then": {
+ "required": ["originalLanguage"]
+ }
+ },
+ "Problem": {
+ "type": "object",
+ "title": "Problem Statement",
+ "description": "Define the problem your proposal aims to solve",
+ "properties": {
+ "statement": {
+ "type": "string",
+ "title": "Problem Description",
+ "description": "Clearly define the problem you aim to solve. This will be visible in the Catalyst voting app.",
+ "minLength": 10,
+ "maxLength": 200,
+ "examples": ["The Cardano ecosystem lacks standardized tools for cross-protocol communication, resulting in fragmented user experiences and inefficient resource utilization."]
+ },
+ "impactArea": {
+ "type": "array",
+ "title": "Impact Areas",
+ "description": "Select the areas that will be most impacted by solving this problem",
+ "items": {
+ "type": "string",
+ "enum": [
+ "Technical Infrastructure",
+ "User Experience",
+ "Developer Tooling",
+ "Community Growth",
+ "Economic Sustainability",
+ "Interoperability",
+ "Security",
+ "Scalability",
+ "Education",
+ "Adoption"
+ ]
+ },
+ "minItems": 1,
+ "maxItems": 3,
+ "uniqueItems": true
+ }
+ },
+ "required": ["statement", "impactArea"]
+ },
+ "Solution": {
+ "type": "object",
+ "title": "Solution Overview",
+ "description": "Describe your proposed solution to the problem",
+ "properties": {
+ "summary": {
+ "type": "string",
+ "title": "Solution Summary",
+ "description": "Briefly describe your solution. Focus on what you will do or create to solve the problem.",
+ "minLength": 10,
+ "maxLength": 200,
+ "examples": ["Develop an open-source integration framework that standardizes protocol communication and provides a unified API layer for seamless DeFi interactions."]
+ },
+ "approach": {
+ "type": "string",
+ "title": "Technical Approach",
+ "description": "Outline the technical approach or methodology you will use",
+ "maxLength": 500
+ },
+ "innovationAspects": {
+ "type": "array",
+ "title": "Innovation Aspects",
+ "description": "Key innovative aspects of your solution",
+ "items": {
+ "type": "string",
+ "maxLength": 100
+ },
+ "minItems": 1,
+ "maxItems": 5,
+ "uniqueItems": true
+ }
+ },
+ "required": ["summary", "approach"]
+ },
+ "SupportingLinks": {
+ "type": "object",
+ "title": "Supporting Documentation",
+ "description": "Additional resources and documentation for your proposal",
+ "properties": {
+ "links": {
+ "type": "array",
+ "title": "Resource Links",
+ "description": "Links to relevant documentation, code repositories, or marketing materials. All links must use HTTPS.",
+ "items": {
+ "type": "object",
+ "properties": {
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https://.*",
+ "title": "Resource URL",
+ "description": "URL must start with https://",
+ "examples": [
+ "https://github.com/your-org/project",
+ "https://your-project-docs.com"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "enum": [
+ "GitHub Repository",
+ "Documentation",
+ "Whitepaper",
+ "Website",
+ "Marketing Material",
+ "Technical Specification",
+ "Research Paper",
+ "Blog Post",
+ "Social Media",
+ "Other"
+ ],
+ "title": "Resource Type",
+ "description": "Type of resource being linked"
+ },
+ "description": {
+ "type": "string",
+ "maxLength": 200,
+ "title": "Resource Description",
+ "description": "Brief description explaining what this resource contains and why it's relevant",
+ "examples": [
+ "Project's main GitHub repository containing all source code",
+ "Technical whitepaper detailing the solution architecture"
+ ]
+ }
+ },
+ "required": ["url", "type", "description"]
+ },
+ "minItems": 0,
+ "maxItems": 10,
+ "uniqueItems": true
+ },
+ "mainRepository": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https://(github\\.com|gitlab\\.com|bitbucket\\.org)/.*",
+ "title": "Main Code Repository",
+ "description": "Primary repository where the project's code will be hosted"
+ },
+ "documentation": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https://.*",
+ "title": "Documentation URL",
+ "description": "Main documentation site or resource for the project"
+ }
+ }
+ },
+ "Dependencies": {
+ "type": "object",
+ "title": "Project Dependencies",
+ "description": "External dependencies and requirements for project success",
+ "properties": {
+ "hasDependencies": {
+ "type": "boolean",
+ "title": "Has Dependencies",
+ "description": "Indicate if your project has any dependencies on other organizations or technologies",
+ "default": false
+ },
+ "details": {
+ "type": "array",
+ "title": "Dependency Details",
+ "description": "List and describe each dependency",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "title": "Dependency Name",
+ "description": "Name of the organization, technology, or resource",
+ "maxLength": 100
+ },
+ "type": {
+ "type": "string",
+ "enum": [
+ "Technical",
+ "Organizational",
+ "Legal",
+ "Financial",
+ "Other"
+ ],
+ "title": "Dependency Type",
+ "description": "Type of dependency"
+ },
+ "description": {
+ "type": "string",
+ "title": "Description",
+ "description": "Explain why this dependency is essential and how it affects your project",
+ "maxLength": 500
+ },
+ "mitigationPlan": {
+ "type": "string",
+ "title": "Mitigation Plan",
+ "description": "How will you handle potential issues with this dependency",
+ "maxLength": 300
+ }
+ },
+ "required": ["name", "type", "description"]
+ },
+ "minItems": 0,
+ "maxItems": 10
+ }
+ },
+ "required": ["hasDependencies"],
+ "dependencies": {
+ "details": ["hasDependencies"]
+ },
+ "if": {
+ "properties": { "hasDependencies": { "const": true } }
+ },
+ "then": {
+ "required": ["details"]
+ }
+ }
+ }
+ },
+ "milestones": {
+ "type": "object",
+ "title": "Project Milestones",
+ "description": "Detailed project milestones and deliverables",
+ "properties": {
+ "milestonesConfig": {
+ "type": "object",
+ "title": "Milestones Configuration",
+ "description": "Configuration for number of milestones based on grant amount",
+ "properties": {
+ "grantAmount": {
+ "type": "number",
+ "title": "Grant Amount in ADA",
+ "description": "Total grant amount requested in ADA",
+ "minimum": 0,
+ "maximum": 1000000
+ },
+ "numberOfMilestones": {
+ "type": "integer",
+ "title": "Number of Milestones",
+ "description": "Total number of milestones including the final milestone",
+ "minimum": 3,
+ "maximum": 10
+ }
+ },
+ "required": ["grantAmount", "numberOfMilestones"]
+ },
+ "milestonesList": {
+ "type": "array",
+ "title": "List of Milestones",
+ "description": "Detailed description of each project milestone",
+ "items": {
+ "type": "object",
+ "title": "Milestone",
+ "properties": {
+ "title": {
+ "type": "string",
+ "title": "Milestone Title",
+ "description": "Short, descriptive title for the milestone",
+ "minLength": 5,
+ "maxLength": 100
+ },
+ "description": {
+ "type": "string",
+ "title": "Milestone Description",
+ "description": "Detailed description of what this milestone entails",
+ "minLength": 50,
+ "maxLength": 1000
+ },
+ "deliverables": {
+ "type": "array",
+ "title": "Deliverables",
+ "description": "Specific outputs and deliverables for this milestone",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "title": "Deliverable Name",
+ "minLength": 5,
+ "maxLength": 100
+ },
+ "description": {
+ "type": "string",
+ "title": "Deliverable Description",
+ "minLength": 20,
+ "maxLength": 500
+ },
+ "type": {
+ "type": "string",
+ "title": "Deliverable Type",
+ "enum": [
+ "Documentation",
+ "Software",
+ "Report",
+ "Presentation",
+ "Video",
+ "Other"
+ ]
+ }
+ },
+ "required": ["name", "description", "type"]
+ },
+ "minItems": 1,
+ "maxItems": 5
+ },
+ "acceptanceCriteria": {
+ "type": "array",
+ "title": "Acceptance Criteria",
+ "description": "Specific criteria that must be met to consider this milestone complete",
+ "items": {
+ "type": "string",
+ "minLength": 10,
+ "maxLength": 200
+ },
+ "minItems": 1,
+ "maxItems": 5
+ },
+ "evidenceOfCompletion": {
+ "type": "array",
+ "title": "Evidence of Completion",
+ "description": "How will you demonstrate that this milestone is complete?",
+ "items": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "title": "Evidence Type",
+ "enum": [
+ "Code Repository",
+ "Documentation",
+ "Demo Video",
+ "Test Results",
+ "Metrics Report",
+ "User Feedback",
+ "Other"
+ ]
+ },
+ "description": {
+ "type": "string",
+ "title": "Evidence Description",
+ "minLength": 20,
+ "maxLength": 300
+ }
+ },
+ "required": ["type", "description"]
+ },
+ "minItems": 1,
+ "maxItems": 3
+ },
+ "timeline": {
+ "type": "object",
+ "title": "Timeline",
+ "properties": {
+ "startDate": {
+ "type": "string",
+ "title": "Start Date",
+ "format": "date"
+ },
+ "endDate": {
+ "type": "string",
+ "title": "End Date",
+ "format": "date"
+ },
+ "durationInWeeks": {
+ "type": "integer",
+ "title": "Duration in Weeks",
+ "minimum": 1,
+ "maximum": 52
+ }
+ },
+ "required": ["startDate", "endDate", "durationInWeeks"]
+ },
+ "budget": {
+ "type": "object",
+ "title": "Milestone Budget",
+ "properties": {
+ "amount": {
+ "type": "number",
+ "title": "Amount in ADA",
+ "minimum": 0
+ },
+ "breakdown": {
+ "type": "array",
+ "title": "Budget Breakdown",
+ "items": {
+ "type": "object",
+ "properties": {
+ "category": {
+ "type": "string",
+ "enum": [
+ "Development",
+ "Design",
+ "Marketing",
+ "Operations",
+ "Other"
+ ]
+ },
+ "amount": {
+ "type": "number",
+ "minimum": 0
+ },
+ "description": {
+ "type": "string",
+ "minLength": 10,
+ "maxLength": 200
+ }
+ },
+ "required": ["category", "amount", "description"]
+ },
+ "minItems": 1
+ }
+ },
+ "required": ["amount", "breakdown"]
+ }
+ },
+ "required": [
+ "title",
+ "description",
+ "deliverables",
+ "acceptanceCriteria",
+ "evidenceOfCompletion",
+ "timeline",
+ "budget"
+ ]
+ },
+ "minItems": 3,
+ "maxItems": 10
+ },
+ "finalMilestone": {
+ "type": "object",
+ "title": "Final Milestone",
+ "description": "Project close-out milestone with final report and video",
+ "properties": {
+ "closeoutReport": {
+ "type": "object",
+ "title": "Project Close-out Report",
+ "properties": {
+ "summary": {
+ "type": "string",
+ "title": "Project Summary",
+ "description": "Overall summary of project achievements",
+ "minLength": 100,
+ "maxLength": 2000
+ },
+ "keyAchievements": {
+ "type": "array",
+ "title": "Key Achievements",
+ "items": {
+ "type": "string",
+ "minLength": 10,
+ "maxLength": 200
+ },
+ "minItems": 1,
+ "maxItems": 10
+ },
+ "lessonsLearned": {
+ "type": "array",
+ "title": "Lessons Learned",
+ "items": {
+ "type": "string",
+ "minLength": 20,
+ "maxLength": 500
+ },
+ "minItems": 1,
+ "maxItems": 5
+ },
+ "futureSteps": {
+ "type": "string",
+ "title": "Future Steps",
+ "description": "Plans for project continuation or future development",
+ "minLength": 50,
+ "maxLength": 1000
+ }
+ },
+ "required": ["summary", "keyAchievements", "lessonsLearned", "futureSteps"]
+ },
+ "demoVideo": {
+ "type": "object",
+ "title": "Project Demo Video",
+ "properties": {
+ "url": {
+ "type": "string",
+ "title": "Video URL",
+ "format": "uri",
+ "pattern": "^https://"
+ },
+ "duration": {
+ "type": "integer",
+ "title": "Duration in Minutes",
+ "minimum": 3,
+ "maximum": 15
+ },
+ "description": {
+ "type": "string",
+ "title": "Video Description",
+ "minLength": 50,
+ "maxLength": 500
+ }
+ },
+ "required": ["url", "duration", "description"]
+ }
+ },
+ "required": ["closeoutReport", "demoVideo"]
+ }
+ },
+ "required": ["milestonesConfig", "milestonesList", "finalMilestone"]
+ },
+ "Horizons": {
+ "type": "object",
+ "title": "Project Horizons",
+ "description": "Long-term vision and categorization of your project",
+ "properties": {
+ "category": {
+ "type": "object",
+ "title": "Project Category",
+ "description": "Select the most relevant category and tags for your project",
+ "properties": {
+ "primaryCategory": {
+ "type": "string",
+ "title": "Primary Category",
+ "description": "Main category that best describes your project",
+ "enum": [
+ "Governance",
+ "Education",
+ "Community & Outreach",
+ "Development & Tools",
+ "Identity & Security",
+ "DeFi",
+ "Real World Applications",
+ "Events & Marketing",
+ "Interoperability",
+ "Legal & Policy",
+ "Sustainability",
+ "Smart Contracts"
+ ]
+ },
+ "subCategory": {
+ "type": "string",
+ "title": "Sub-category",
+ "description": "Specific area within the main category",
+ "enum": {
+ "Governance": [
+ "DAO",
+ "Voting",
+ "Treasury Management"
+ ],
+ "Education": [
+ "Learn to Earn",
+ "Training",
+ "Translation"
+ ],
+ "Community & Outreach": [
+ "Connected Community",
+ "Social Media",
+ "Community Building"
+ ],
+ "Development & Tools": [
+ "Developer Tools",
+ "L2 Infrastructure",
+ "Analytics",
+ "AI Research",
+ "UTXO",
+ "P2P"
+ ],
+ "Identity & Security": [
+ "Identity & Verification",
+ "Cybersecurity",
+ "Authentication",
+ "Privacy"
+ ],
+ "DeFi": [
+ "Payments",
+ "Stablecoin",
+ "Risk Management",
+ "Yield",
+ "Staking",
+ "Lending"
+ ],
+ "Real World Applications": [
+ "Wallet",
+ "Marketplace",
+ "Manufacturing",
+ "IoT",
+ "Financial Services",
+ "E-commerce",
+ "Business Services",
+ "Supply Chain",
+ "Real Estate",
+ "Healthcare",
+ "Tourism",
+ "Entertainment",
+ "RWA",
+ "Music",
+ "Tokenization"
+ ],
+ "Events & Marketing": [
+ "Events",
+ "Marketing",
+ "Hackathons",
+ "Accelerator",
+ "Incubator"
+ ],
+ "Interoperability": [
+ "Cross-chain",
+ "Off-chain",
+ "Bridges"
+ ],
+ "Legal & Policy": [
+ "Policy",
+ "Advocacy",
+ "Standards",
+ "Compliance"
+ ],
+ "Sustainability": [
+ "Environment",
+ "Agriculture",
+ "Clean Energy"
+ ],
+ "Smart Contracts": [
+ "Development",
+ "Security",
+ "Templates",
+ "Auditing"
+ ]
+ }
+ }
+ }
+ },
+ "tags": {
+ "type": "array",
+ "title": "Project Tags",
+ "description": "Additional tags to help categorize your project",
+ "items": {
+ "type": "string",
+ "minLength": 2,
+ "maxLength": 30
+ },
+ "minItems": 1,
+ "maxItems": 5,
+ "uniqueItems": true
+ },
+ "impact": {
+ "type": "object",
+ "title": "Project Impact",
+ "description": "Describe the expected impact of your project",
+ "properties": {
+ "timeframe": {
+ "type": "string",
+ "enum": [
+ "Short-term (0-6 months)",
+ "Medium-term (6-18 months)",
+ "Long-term (18+ months)"
+ ],
+ "title": "Impact Timeframe",
+ "description": "Expected timeframe to see meaningful impact"
+ },
+ "scale": {
+ "type": "string",
+ "enum": [
+ "Local",
+ "Regional",
+ "Global"
+ ],
+ "title": "Impact Scale",
+ "description": "Geographic scale of impact"
+ },
+ "metrics": {
+ "type": "array",
+ "title": "Impact Metrics",
+ "description": "Key metrics to measure project success",
+ "items": {
+ "type": "object",
+ "properties": {
+ "metric": {
+ "type": "string",
+ "title": "Metric Name",
+ "description": "Name of the metric",
+ "maxLength": 100
+ },
+ "target": {
+ "type": "string",
+ "title": "Target Value",
+ "description": "Target value or goal for this metric",
+ "maxLength": 100
+ },
+ "measurement": {
+ "type": "string",
+ "title": "Measurement Method",
+ "description": "How this metric will be measured",
+ "maxLength": 200
+ }
+ },
+ "required": ["metric", "target", "measurement"]
+ },
+ "minItems": 1,
+ "maxItems": 5
+ }
+ },
+ "required": ["timeframe", "scale", "metrics"]
+ }
+ },
+ "required": ["primaryCategory", "subCategory", "tags", "impact"]
+ },
+ "proposalDetails": {
+ "type": "object",
+ "title": "Proposal Details",
+ "description": "Detailed information about your proposal's solution, impact, and feasibility",
+ "properties": {
+ "solution": {
+ "type": "object",
+ "title": "Solution Description",
+ "description": "Detailed description of your proposed solution",
+ "properties": {
+ "description": {
+ "type": "string",
+ "title": "Solution Description",
+ "description": "Provide a comprehensive description of your proposed solution",
+ "minLength": 100,
+ "maxLength": 2000,
+ "examples": [
+ "Our solution involves developing a decentralized education platform that will..."
+ ]
+ },
+ "uniqueValue": {
+ "type": "string",
+ "title": "Unique Value Proposition",
+ "description": "What makes your solution unique and innovative?",
+ "minLength": 50,
+ "maxLength": 500
+ },
+ "targetAudience": {
+ "type": "array",
+ "title": "Target Audience",
+ "description": "Who will benefit from your solution?",
+ "items": {
+ "type": "string",
+ "minLength": 5,
+ "maxLength": 100
+ },
+ "minItems": 1,
+ "maxItems": 5,
+ "uniqueItems": true
+ },
+ "implementation": {
+ "type": "string",
+ "title": "Implementation Approach",
+ "description": "How will you implement your solution?",
+ "minLength": 100,
+ "maxLength": 1000
+ }
+ },
+ "required": ["description", "uniqueValue", "targetAudience", "implementation"]
+ },
+ "impact": {
+ "type": "object",
+ "title": "Project Impact",
+ "description": "Define and measure the impact of your project",
+ "properties": {
+ "communityBenefit": {
+ "type": "string",
+ "title": "Community Benefit",
+ "description": "How will the Cardano community benefit from your project?",
+ "minLength": 100,
+ "maxLength": 1000
+ },
+ "metrics": {
+ "type": "array",
+ "title": "Impact Metrics",
+ "description": "Specific metrics to measure project success",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "title": "Metric Name",
+ "minLength": 5,
+ "maxLength": 100
+ },
+ "description": {
+ "type": "string",
+ "title": "Metric Description",
+ "minLength": 20,
+ "maxLength": 300
+ },
+ "target": {
+ "type": "string",
+ "title": "Target Value",
+ "minLength": 1,
+ "maxLength": 100
+ },
+ "measurement": {
+ "type": "string",
+ "title": "Measurement Method",
+ "minLength": 20,
+ "maxLength": 300
+ }
+ },
+ "required": ["name", "description", "target", "measurement"]
+ },
+ "minItems": 2,
+ "maxItems": 5
+ },
+ "outputs": {
+ "type": "array",
+ "title": "Project Outputs",
+ "description": "Tangible outputs and deliverables from the project",
+ "items": {
+ "type": "string",
+ "minLength": 10,
+ "maxLength": 200
+ },
+ "minItems": 1,
+ "maxItems": 10,
+ "uniqueItems": true
+ }
+ },
+ "required": ["communityBenefit", "metrics", "outputs"]
+ },
+ "capability": {
+ "type": "object",
+ "title": "Capability & Feasibility",
+ "description": "Demonstrate your ability to deliver the project successfully",
+ "properties": {
+ "teamExperience": {
+ "type": "string",
+ "title": "Team Experience",
+ "description": "Describe your team's relevant experience and capabilities",
+ "minLength": 100,
+ "maxLength": 1000
+ },
+ "feasibilityApproach": {
+ "type": "string",
+ "title": "Feasibility Approach",
+ "description": "How will you validate the feasibility of your approach?",
+ "minLength": 100,
+ "maxLength": 1000
+ },
+ "riskMitigation": {
+ "type": "array",
+ "title": "Risk Mitigation",
+ "description": "Key risks and mitigation strategies",
+ "items": {
+ "type": "object",
+ "properties": {
+ "risk": {
+ "type": "string",
+ "title": "Risk Description",
+ "minLength": 10,
+ "maxLength": 200
+ },
+ "impact": {
+ "type": "string",
+ "enum": ["Low", "Medium", "High"],
+ "title": "Risk Impact"
+ },
+ "mitigation": {
+ "type": "string",
+ "title": "Mitigation Strategy",
+ "minLength": 20,
+ "maxLength": 300
+ }
+ },
+ "required": ["risk", "impact", "mitigation"]
+ },
+ "minItems": 1,
+ "maxItems": 5
+ },
+ "fundManagement": {
+ "type": "string",
+ "title": "Fund Management",
+ "description": "How will you ensure proper management and accountability of funds?",
+ "minLength": 100,
+ "maxLength": 1000
+ }
+ },
+ "required": ["teamExperience", "feasibilityApproach", "riskMitigation", "fundManagement"]
+ }
+ },
+ "required": ["solution", "impact", "capability"]
+ },
+ "finalPitch": {
+ "type": "object",
+ "title": "Final Pitch",
+ "description": "Final project pitch including team, budget, and value proposition",
+ "properties": {
+ "team": {
+ "type": "object",
+ "title": "Team Information",
+ "description": "Details about the project team and their capabilities",
+ "properties": {
+ "members": {
+ "type": "array",
+ "title": "Team Members",
+ "description": "List of team members and their roles",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "title": "Name",
+ "description": "Full name of the team member",
+ "minLength": 2,
+ "maxLength": 100
+ },
+ "role": {
+ "type": "string",
+ "title": "Role",
+ "description": "Primary role in the project",
+ "minLength": 5,
+ "maxLength": 100
+ },
+ "expertise": {
+ "type": "array",
+ "title": "Areas of Expertise",
+ "items": {
+ "type": "string",
+ "minLength": 3,
+ "maxLength": 50
+ },
+ "minItems": 1,
+ "maxItems": 5,
+ "uniqueItems": true
+ },
+ "experience": {
+ "type": "string",
+ "title": "Relevant Experience",
+ "description": "Brief description of relevant experience",
+ "minLength": 50,
+ "maxLength": 500
+ },
+ "links": {
+ "type": "array",
+ "title": "Professional Links",
+ "description": "Links to professional profiles or past work",
+ "items": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "LinkedIn",
+ "GitHub",
+ "Portfolio",
+ "Twitter",
+ "Website",
+ "Other"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https://"
+ },
+ "description": {
+ "type": "string",
+ "maxLength": 100
+ }
+ },
+ "required": ["type", "url"]
+ },
+ "maxItems": 5
+ }
+ },
+ "required": ["name", "role", "expertise", "experience"]
+ },
+ "minItems": 1,
+ "maxItems": 10
+ },
+ "teamCapabilities": {
+ "type": "string",
+ "title": "Team Capabilities",
+ "description": "Overview of the team's collective capabilities and why they are best suited for this project",
+ "minLength": 100,
+ "maxLength": 1000
+ },
+ "previousWork": {
+ "type": "array",
+ "title": "Previous Work",
+ "description": "Examples of relevant previous work or projects",
+ "items": {
+ "type": "object",
+ "properties": {
+ "projectName": {
+ "type": "string",
+ "title": "Project Name",
+ "minLength": 3,
+ "maxLength": 100
+ },
+ "description": {
+ "type": "string",
+ "title": "Project Description",
+ "minLength": 50,
+ "maxLength": 500
+ },
+ "relevance": {
+ "type": "string",
+ "title": "Relevance to Current Proposal",
+ "minLength": 50,
+ "maxLength": 300
+ },
+ "url": {
+ "type": "string",
+ "title": "Project URL",
+ "format": "uri",
+ "pattern": "^https://"
+ }
+ },
+ "required": ["projectName", "description", "relevance"]
+ },
+ "maxItems": 5
+ }
+ },
+ "required": ["members", "teamCapabilities"]
+ },
+ "budget": {
+ "type": "object",
+ "title": "Budget Details",
+ "description": "Detailed budget breakdown and justification",
+ "properties": {
+ "totalBudget": {
+ "type": "number",
+ "title": "Total Budget (ADA)",
+ "description": "Total amount requested in ADA",
+ "minimum": 0,
+ "maximum": 1000000
+ },
+ "categories": {
+ "type": "array",
+ "title": "Budget Categories",
+ "description": "Breakdown of budget by category",
+ "items": {
+ "type": "object",
+ "properties": {
+ "category": {
+ "type": "string",
+ "enum": [
+ "Development",
+ "Design",
+ "Marketing",
+ "Operations",
+ "Research",
+ "Community Management",
+ "Legal",
+ "Other"
+ ]
+ },
+ "amount": {
+ "type": "number",
+ "minimum": 0
+ },
+ "description": {
+ "type": "string",
+ "minLength": 20,
+ "maxLength": 300
+ },
+ "breakdown": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "item": {
+ "type": "string",
+ "minLength": 5,
+ "maxLength": 100
+ },
+ "cost": {
+ "type": "number",
+ "minimum": 0
+ },
+ "justification": {
+ "type": "string",
+ "minLength": 20,
+ "maxLength": 200
+ }
+ },
+ "required": ["item", "cost", "justification"]
+ },
+ "minItems": 1
+ }
+ },
+ "required": ["category", "amount", "description", "breakdown"]
+ },
+ "minItems": 1
+ },
+ "timeline": {
+ "type": "object",
+ "title": "Budget Timeline",
+ "properties": {
+ "distributionSchedule": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "milestone": {
+ "type": "string",
+ "minLength": 5,
+ "maxLength": 100
+ },
+ "amount": {
+ "type": "number",
+ "minimum": 0
+ },
+ "percentage": {
+ "type": "number",
+ "minimum": 0,
+ "maximum": 100
+ }
+ },
+ "required": ["milestone", "amount", "percentage"]
+ },
+ "minItems": 1
+ }
+ },
+ "required": ["distributionSchedule"]
+ }
+ },
+ "required": ["totalBudget", "categories", "timeline"]
+ },
+ "valueProposition": {
+ "type": "object",
+ "title": "Value Proposition",
+ "description": "Justification of the project's value for money",
+ "properties": {
+ "costBenefitAnalysis": {
+ "type": "string",
+ "title": "Cost-Benefit Analysis",
+ "description": "Analysis of the project's costs versus its benefits to the Cardano ecosystem",
+ "minLength": 100,
+ "maxLength": 1000
+ },
+ "impactMetrics": {
+ "type": "array",
+ "title": "Impact Metrics",
+ "description": "Specific metrics that demonstrate value for money",
+ "items": {
+ "type": "object",
+ "properties": {
+ "metric": {
+ "type": "string",
+ "title": "Metric Name",
+ "minLength": 5,
+ "maxLength": 100
+ },
+ "target": {
+ "type": "string",
+ "title": "Target Value",
+ "minLength": 1,
+ "maxLength": 100
+ },
+ "justification": {
+ "type": "string",
+ "title": "Value Justification",
+ "minLength": 50,
+ "maxLength": 300
+ }
+ },
+ "required": ["metric", "target", "justification"]
+ },
+ "minItems": 2,
+ "maxItems": 5
+ },
+ "longTermValue": {
+ "type": "string",
+ "title": "Long-term Value",
+ "description": "Description of the long-term value and sustainability of the project",
+ "minLength": 100,
+ "maxLength": 1000
+ },
+ "communityBenefits": {
+ "type": "array",
+ "title": "Community Benefits",
+ "description": "Specific benefits to the Cardano community",
+ "items": {
+ "type": "string",
+ "minLength": 20,
+ "maxLength": 200
+ },
+ "minItems": 2,
+ "maxItems": 5
+ }
+ },
+ "required": ["costBenefitAnalysis", "impactMetrics", "longTermValue", "communityBenefits"]
+ }
+ },
+ "required": ["team", "budget", "valueProposition"]
+ },
+ "mandatoryAcknowledgments": {
+ "type": "object",
+ "title": "Mandatory Acknowledgments",
+ "description": "Required acknowledgments and agreements for proposal submission",
+ "properties": {
+ "fundRules": {
+ "type": "object",
+ "title": "Fund Rules Agreement",
+ "properties": {
+ "acknowledgment": {
+ "type": "boolean",
+ "title": "Fund Rules Acknowledgment",
+ "description": "I confirm that I have read and agree to be bound by the Fund Rules",
+ "const": true
+ },
+ "version": {
+ "type": "string",
+ "title": "Fund Rules Version",
+ "description": "Version of the Fund Rules being acknowledged",
+ "pattern": "^F[0-9]+$"
+ },
+ "timestamp": {
+ "type": "string",
+ "title": "Acknowledgment Timestamp",
+ "description": "When the rules were acknowledged",
+ "format": "date-time"
+ }
+ },
+ "required": ["acknowledgment", "version", "timestamp"]
+ },
+ "termsAndConditions": {
+ "type": "object",
+ "title": "Terms and Conditions Agreement",
+ "properties": {
+ "acknowledgment": {
+ "type": "boolean",
+ "title": "Terms and Conditions Acknowledgment",
+ "description": "I confirm that I have read and agree to be bound by the Project Catalyst Terms and Conditions",
+ "const": true
+ },
+ "version": {
+ "type": "string",
+ "title": "Terms Version",
+ "description": "Version of the Terms and Conditions being acknowledged",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "timestamp": {
+ "type": "string",
+ "title": "Acknowledgment Timestamp",
+ "description": "When the terms were acknowledged",
+ "format": "date-time"
+ }
+ },
+ "required": ["acknowledgment", "version", "timestamp"]
+ },
+ "privacyPolicy": {
+ "type": "object",
+ "title": "Privacy Policy Agreement",
+ "properties": {
+ "acknowledgment": {
+ "type": "boolean",
+ "title": "Privacy Policy Acknowledgment",
+ "description": "I acknowledge and agree that any data I share will be processed in accordance with the Catalyst FCS Privacy Policy",
+ "const": true
+ },
+ "version": {
+ "type": "string",
+ "title": "Privacy Policy Version",
+ "description": "Version of the Privacy Policy being acknowledged",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "timestamp": {
+ "type": "string",
+ "title": "Acknowledgment Timestamp",
+ "description": "When the privacy policy was acknowledged",
+ "format": "date-time"
+ }
+ },
+ "required": ["acknowledgment", "version", "timestamp"]
+ },
+ "intellectualProperty": {
+ "type": "object",
+ "title": "Intellectual Property Declaration",
+ "properties": {
+ "acknowledgment": {
+ "type": "boolean",
+ "title": "IP Rights Acknowledgment",
+ "description": "I confirm that I have the necessary rights to all intellectual property included in this proposal",
+ "const": true
+ },
+ "details": {
+ "type": "string",
+ "title": "IP Details",
+ "description": "Additional details about intellectual property rights (if applicable)",
+ "maxLength": 1000
+ },
+ "timestamp": {
+ "type": "string",
+ "title": "Acknowledgment Timestamp",
+ "description": "When the IP declaration was made",
+ "format": "date-time"
+ }
+ },
+ "required": ["acknowledgment", "timestamp"]
+ },
+ "compliance": {
+ "type": "object",
+ "title": "Compliance Declaration",
+ "properties": {
+ "legalCompliance": {
+ "type": "boolean",
+ "title": "Legal Compliance",
+ "description": "I confirm that my proposal complies with all applicable laws and regulations",
+ "const": true
+ },
+ "noConflictOfInterest": {
+ "type": "boolean",
+ "title": "No Conflict of Interest",
+ "description": "I confirm that there are no undisclosed conflicts of interest",
+ "const": true
+ },
+ "accurateInformation": {
+ "type": "boolean",
+ "title": "Information Accuracy",
+ "description": "I confirm that all information provided is accurate and complete",
+ "const": true
+ },
+ "timestamp": {
+ "type": "string",
+ "title": "Acknowledgment Timestamp",
+ "description": "When the compliance declaration was made",
+ "format": "date-time"
+ }
+ },
+ "required": ["legalCompliance", "noConflictOfInterest", "accurateInformation", "timestamp"]
+ },
+ "additionalAcknowledgments": {
+ "type": "array",
+ "title": "Additional Acknowledgments",
+ "description": "Any additional acknowledgments required for specific proposal types",
+ "items": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "title": "Acknowledgment Type",
+ "minLength": 5,
+ "maxLength": 100
+ },
+ "acknowledgment": {
+ "type": "boolean",
+ "title": "Acknowledgment",
+ "const": true
+ },
+ "description": {
+ "type": "string",
+ "title": "Description",
+ "description": "Detailed description of what is being acknowledged",
+ "minLength": 10,
+ "maxLength": 500
+ },
+ "timestamp": {
+ "type": "string",
+ "title": "Acknowledgment Timestamp",
+ "format": "date-time"
+ }
+ },
+ "required": ["type", "acknowledgment", "description", "timestamp"]
+ }
+ }
+ },
+ "required": [
+ "fundRules",
+ "termsAndConditions",
+ "privacyPolicy",
+ "intellectualProperty",
+ "compliance"
+ ]
+ }
+ }
+}
\ No newline at end of file
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/proposalTemplate.F14.example.json b/docs/src/architecture/08_concepts/document_templates/proposal/proposalTemplate.F14.example.json
deleted file mode 100644
index 27a616b7cc3..00000000000
--- a/docs/src/architecture/08_concepts/document_templates/proposal/proposalTemplate.F14.example.json
+++ /dev/null
@@ -1,105 +0,0 @@
-{
- "$schema": "./proposalTemplate.F14.schema.json",
- "template_version": {
- "description": "The version of the schema, formatted as a ULID.",
- "title": "Version",
- "uid": "version_section",
- "value": "01F8MECHZXK8F8D8F8D8F8D8F9"
- },
- "category_segment": {
- "description": "Details about the categories related to the proposal.",
- "title": "Category Segment",
- "uid": "category_segment_section",
- "value": {
- "additional_questions": {
- "description": "Details about additional questions regarding the project.",
- "title": "Additional Questions",
- "uid": "additional_questions_section",
- "value": {
- "is_open_source": true,
- "license_type": "anything i please",
- "product_repository_url": "http://somwhere.test/a/project/url",
- "project_documentation_url": "http://somwhere.test/a/project/url/for/documentation"
- }
- },
- "agreements": {
- "description": "Terms and agreements for the proposal.",
- "title": "Terms and Agreements",
- "uid": "agreements_section",
- "value": {
- "agree_fund_rules": false,
- "catalyst_terms_and_conditions": false,
- "privacy_policy": true
- }
- },
- "milestones": {
- "description": "Milestones to track project progress.",
- "title": "Project Milestones",
- "uid": "milestones_section",
- "value": [
- {
- "deliverables": [
- "something",
- "something else"
- ],
- "description": "a multi lin\\nstring",
- "title": "a single line string"
- }
- ]
- },
- "resources": {
- "description": "Information about resources and budget allocation.",
- "title": "Resources and Budget",
- "uid": "resources_section",
- "value": {
- "budget_breakdown": "multi\\nline\\nstring",
- "project_team": [
- {
- "experience": "multi\\nline\\nstring",
- "role": "manager"
- }
- ]
- }
- }
- }
- },
- "category_template": {
- "description": "The category to which this template belongs.",
- "title": "Category",
- "uid": "category_section",
- "value": "can_be_any_value_without_whitespace"
- },
- "proposal_setup_segment": {
- "description": "Basic information about your proposal.",
- "title": "Proposal Setup",
- "uid": "proposal_setup_section",
- "value": {
- "proposal_title": {
- "description": "The name of the proposal.",
- "title": "Proposal Title",
- "uid": "proposal_title_field_section",
- "value": "a proposal title single line"
- }
- }
- },
- "proposal_summary_segment": {
- "description": "Detailed information about the proposal.",
- "title": "Proposal Details",
- "uid": "proposal_details_section",
- "value": {
- "proposal_problem": "a\\nmultiline\\nproblem",
- "proposal_solution": "a\\nmultiline\\nsolution"
- }
- },
- "public_description_segment": {
- "description": "Detailed public description information.",
- "title": "Public Description",
- "uid": "public_description_section",
- "value": {
- "topic_1": "topic 1",
- "topic_2": "topic 2",
- "topic_3": "topic 3",
- "topic_4": "topic 4"
- }
- }
-}
\ No newline at end of file
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/proposalTemplate.F14.schema.json b/docs/src/architecture/08_concepts/document_templates/proposal/proposalTemplate.F14.schema.json
deleted file mode 100644
index 8583da87505..00000000000
--- a/docs/src/architecture/08_concepts/document_templates/proposal/proposalTemplate.F14.schema.json
+++ /dev/null
@@ -1,401 +0,0 @@
-{
- "$schema": "http://json-schema.org/draft-07/schema#",
- "title": "Catalyst Fund 14 Base Proposal Template",
- "description": "A structured template for creating Fund 14 proposals",
- "type": "object",
- "properties": {
- "template_version": {
- "type": "object",
- "properties": {
- "uid": {
- "const": "version_section",
- "description": "Unique identifier for the version."
- },
- "title": {
- "const": "Version",
- "description": "Title of the version."
- },
- "description": {
- "const": "The version of the schema, formatted as a ULID.",
- "description": "Description for the version."
- },
- "value": {
- "type": "string",
- "description": "A unique identifier for the version, formatted as a ULID.",
- "pattern": "^[0-9A-HJKMNP-TV-Z]{26}$",
- "default": "01F8MECHZXK8F8D8F8D8F8D8F8"
- }
- },
- "required": ["uid", "title", "description", "value"]
- },
- "category_template": {
- "type": "object",
- "properties": {
- "uid": {
- "const": "category_section",
- "description": "Unique identifier for the category."
- },
- "title": {
- "const": "Category",
- "description": "Title of the category."
- },
- "description": {
- "const": "The category to which this template belongs.",
- "description": "Description for the category."
- },
- "value": {
- "type": "string",
- "description": "A unique identifier for the category.",
- "pattern": "^[a-zA-Z0-9_-]+$",
- "default": "cardano_open_category"
- }
- },
- "required": ["uid", "title", "description", "value"]
- },
- "proposal_setup_segment": {
- "type": "object",
- "properties": {
- "uid": {
- "const": "proposal_setup_section",
- "description": "Unique identifier for the Proposal Setup Segment."
- },
- "title": {
- "const": "Proposal Setup",
- "description": "Title of the Proposal Setup Segment."
- },
- "description": {
- "const": "Basic information about your proposal.",
- "description": "Description for the Proposal Setup Segment."
- },
- "value": {
- "type": "object",
- "properties": {
- "proposal_title": {
- "type": "object",
- "properties": {
- "uid": {
- "const": "proposal_title_field_section",
- "description": "Unique identifier for the Proposal Title field."
- },
- "title": {
- "const": "Proposal Title",
- "description": "Title of the Proposal Title field."
- },
- "description": {
- "const": "The name of the proposal.",
- "description": "Description for the Proposal Title field."
- },
- "value": {
- "type": "string",
- "maxLength": 60,
- "description": "User-provided proposal title.",
- "format": "string",
- "pattern": "^[a-zA-Z0-9 ]+$"
- }
- },
- "required": ["uid", "title", "description", "value"]
- }
- }
- }
- },
- "required": ["uid", "title", "description", "value"]
- },
- "proposal_summary_segment": {
- "type": "object",
- "properties": {
- "uid": {
- "const": "proposal_details_section",
- "description": "Unique identifier for the Proposal Details."
- },
- "title": {
- "const": "Proposal Details",
- "description": "Details about the proposal."
- },
- "description": {
- "const": "Detailed information about the proposal.",
- "description": "Description for the Proposal Details."
- },
- "value": {
- "type": "object",
- "properties": {
- "proposal_problem": {
- "type": "string",
- "description": "Describe the problem you're addressing in the Cardano ecosystem.",
- "maxLength": 1000,
- "format": "string",
- "pattern": "^[\\s\\S]*$"
- },
- "proposal_solution": {
- "type": "string",
- "description": "Describe your solution and how it addresses the problem.",
- "maxLength": 2000,
- "format": "string",
- "pattern": "^[\\s\\S]*$"
- }
- },
- "required": ["proposal_problem", "proposal_solution"]
- }
- },
- "required": ["uid", "title", "description", "value"]
- },
- "public_description_segment": {
- "type": "object",
- "properties": {
- "uid": {
- "const": "public_description_section",
- "description": "Unique identifier for the Public Description Segment."
- },
- "title": {
- "const": "Public Description",
- "description": "Public description of the proposal."
- },
- "description": {
- "const": "Detailed public description information.",
- "description": "Description for the Public Description Segment."
- },
- "value": {
- "type": "object",
- "properties": {
- "topic_1": {
- "type": "string",
- "description": "First topic of the public description.",
- "maxLength": 500,
- "format": "string",
- "pattern": "^[a-zA-Z0-9 ]+$"
- },
- "topic_2": {
- "type": "string",
- "description": "Second topic of the public description.",
- "maxLength": 500,
- "format": "string",
- "pattern": "^[a-zA-Z0-9 ]+$"
- },
- "topic_3": {
- "type": "string",
- "description": "Third topic of the public description.",
- "maxLength": 500,
- "format": "string",
- "pattern": "^[a-zA-Z0-9 ]+$"
- },
- "topic_4": {
- "type": "string",
- "description": "Fourth topic of the public description.",
- "maxLength": 500,
- "format": "string",
- "pattern": "^[a-zA-Z0-9 ]+$"
- }
- },
- "required": ["topic_1", "topic_2", "topic_3", "topic_4"]
- }
- },
- "required": ["uid", "title", "description", "value"]
- },
- "category_segment": {
- "type": "object",
- "properties": {
- "uid": {
- "const": "category_segment_section",
- "description": "Unique identifier for the Category Segment."
- },
- "title": {
- "const": "Category Segment",
- "description": "Segment for categorizing the proposal."
- },
- "description": {
- "const": "Details about the categories related to the proposal.",
- "description": "Description for the Category Segment."
- },
- "value": {
- "type": "object",
- "properties": {
- "additional_questions": {
- "type": "object",
- "properties": {
- "uid": {
- "const": "additional_questions_section",
- "description": "Unique identifier for Additional Questions."
- },
- "title": {
- "const": "Additional Questions",
- "description": "Questions related to the project."
- },
- "description": {
- "const": "Details about additional questions regarding the project.",
- "description": "Description for Additional Questions."
- },
- "value": {
- "type": "object",
- "properties": {
- "is_open_source": {
- "type": "boolean",
- "description": "Is the project open source?"
- },
- "license_type": {
- "type": "string",
- "description": "Type of license used.",
- "format": "string",
- "pattern": "^[a-zA-Z0-9 ]+$"
- },
- "product_repository_url": {
- "type": "string",
- "format": "uri",
- "description": "URL to the product repository."
- },
- "project_documentation_url": {
- "type": "string",
- "format": "uri",
- "description": "URL to project documentation."
- }
- },
- "required": ["is_open_source", "license_type", "product_repository_url", "project_documentation_url"]
- }
- },
- "required": ["uid", "title", "description", "value"]
- },
- "milestones": {
- "type": "object",
- "properties": {
- "uid": {
- "const": "milestones_section",
- "description": "Unique identifier for the Project Milestones."
- },
- "title": {
- "const": "Project Milestones",
- "description": "Milestones for the project."
- },
- "description": {
- "const": "Milestones to track project progress.",
- "description": "Description for the Project Milestones."
- },
- "value": {
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "title": {
- "type": "string",
- "description": "Milestone Title.",
- "maxLength": 100,
- "format": "string",
- "pattern": "^[a-zA-Z0-9 ]+$"
- },
- "description": {
- "type": "string",
- "description": "Milestone Description.",
- "maxLength": 500,
- "format": "string",
- "pattern": "^[\\s\\S]*$"
- },
- "deliverables": {
- "type": "array",
- "items": {
- "type": "string",
- "format": "string",
- "pattern": "^[a-zA-Z0-9 ]+$"
- }
- }
- },
- "required": ["title", "description", "deliverables"]
- }
- }
- },
- "required": ["uid", "title", "description", "value"]
- },
- "resources": {
- "type": "object",
- "properties": {
- "uid": {
- "const": "resources_section",
- "description": "Unique identifier for Resources and Budget."
- },
- "title": {
- "const": "Resources and Budget",
- "description": "Details about resources and budget."
- },
- "description": {
- "const": "Information about resources and budget allocation.",
- "description": "Description for Resources and Budget."
- },
- "value": {
- "type": "object",
- "properties": {
- "project_team": {
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "role": {
- "type": "string",
- "description": "Role of the team member.",
- "maxLength": 100,
- "format": "string",
- "pattern": "^[a-zA-Z0-9 ]+$"
- },
- "experience": {
- "type": "string",
- "description": "Relevant experience of the team member.",
- "maxLength": 500,
- "format": "string",
- "pattern": "^[\\s\\S]*$"
- }
- },
- "required": ["role", "experience"]
- }
- },
- "budget_breakdown": {
- "type": "string",
- "description": "Detailed breakdown of how the funds will be used.",
- "maxLength": 2000,
- "format": "string",
- "pattern": "^[\\s\\S]*$"
- }
- },
- "required": ["project_team", "budget_breakdown"]
- }
- },
- "required": ["uid", "title", "description", "value"]
- },
- "agreements": {
- "type": "object",
- "properties": {
- "uid": {
- "const": "agreements_section",
- "description": "Unique identifier for Terms and Agreements."
- },
- "title": {
- "const": "Terms and Agreements",
- "description": "Agreements related to the proposal."
- },
- "description": {
- "const": "Terms and agreements for the proposal.",
- "description": "Description for Terms and Agreements."
- },
- "value": {
- "type": "object",
- "properties": {
- "agree_fund_rules": {
- "type": "boolean",
- "description": "Agreement to fund rules."
- },
- "catalyst_terms_and_conditions": {
- "type": "boolean",
- "description": "Agreement to terms and conditions."
- },
- "privacy_policy": {
- "type": "boolean",
- "description": "Agreement to privacy policy."
- }
- },
- "required": ["agree_fund_rules", "catalyst_terms_and_conditions", "privacy_policy"]
- }
- },
- "required": ["uid", "title", "description", "value"]
- }
- },
- "required": ["additional_questions", "milestones", "resources", "agreements"]
- }
- },
- "required": ["uid", "title", "description", "value"]
- }
- }
-}
\ No newline at end of file
From 0496a040ac711e2722ff559bfaba38568682de0e Mon Sep 17 00:00:00 2001
From: Nathan Bogale
Date: Wed, 4 Dec 2024 22:12:35 +0300
Subject: [PATCH 04/25] feat(cat-gateway: added proposal schema and example of
f14 templates
---
.../F14-Generic/example.proposal.json | 142 +++
.../proposalTemplate.F14.schema.json | 856 ++++++++++--------
2 files changed, 613 insertions(+), 385 deletions(-)
create mode 100644 docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/example.proposal.json
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/example.proposal.json b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/example.proposal.json
new file mode 100644
index 00000000000..bd5def1aaa7
--- /dev/null
+++ b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/example.proposal.json
@@ -0,0 +1,142 @@
+{
+ "$schema": "./proposalTemplate.F14.schema.json",
+ "setup": {
+ "title": {
+ "title": "Cardano DeFi Integration Platform"
+ },
+ "proposer": {
+ "mainApplicant": "John Smith",
+ "applicant_type": "Entity (Incorporated)",
+ "co-proposers": ["Alice Johnson", "Bob Wilson"]
+ }
+ },
+ "proposalSummary": {
+ "budget": {
+ "requestedFunds": 500000
+ },
+ "problem": {
+ "description": "Current DeFi platforms on Cardano lack seamless integration capabilities, making it difficult for developers to build interconnected financial applications.",
+ "relevance": "This problem affects the entire Cardano ecosystem by limiting the growth and adoption of DeFi applications."
+ },
+ "supportingLinks": {
+ "documentation": "https://example.com/project-docs",
+ "github": "https://github.com/example/defi-platform",
+ "media": ["https://example.com/demo-video"]
+ }
+ },
+ "horizons": {
+ "category": {
+ "primaryCategory": "DeFi",
+ "subCategory": "Integration Tools"
+ },
+ "tags": ["defi", "integration", "developer-tools", "smart-contracts"]
+ },
+ "proposalDetails": {
+ "solution": {
+ "description": "Our platform will provide a unified API layer that enables seamless integration between different DeFi protocols on Cardano.",
+ "features": [
+ "Standardized API endpoints",
+ "Smart contract templates",
+ "Cross-protocol liquidity management"
+ ]
+ },
+ "impact": {
+ "metrics": [
+ "Number of integrated protocols",
+ "Developer adoption rate",
+ "Transaction volume through the platform"
+ ],
+ "targetAudience": "DeFi developers and protocol creators on Cardano"
+ },
+ "capability": {
+ "teamExperience": "Our team has 5+ years of experience in DeFi development and Cardano ecosystem",
+ "resources": "Fully equipped development team with blockchain expertise"
+ }
+ },
+ "milestones": {
+ "milestonesConfig": {
+ "count": 4,
+ "duration": "6 months"
+ },
+ "milestonesList": [
+ {
+ "title": "Architecture Design",
+ "description": "Complete system architecture and API specifications",
+ "deliverables": ["Architecture documentation", "API specifications"],
+ "budget": {
+ "amount": 100000
+ }
+ },
+ {
+ "title": "Core Development",
+ "description": "Develop core integration layer and smart contracts",
+ "deliverables": ["Core platform code", "Smart contract templates"],
+ "budget": {
+ "amount": 200000
+ }
+ },
+ {
+ "title": "Testing and Integration",
+ "description": "Comprehensive testing and initial protocol integrations",
+ "deliverables": ["Test reports", "Integration documentation"],
+ "budget": {
+ "amount": 150000
+ }
+ }
+ ],
+ "finalMilestone": {
+ "title": "Launch and Documentation",
+ "deliverables": ["Platform launch", "Complete documentation", "Video demonstration"],
+ "budget": {
+ "amount": 50000
+ }
+ }
+ },
+ "finalPitch": {
+ "team": {
+ "members": [
+ {
+ "name": "John Smith",
+ "role": "Project Lead",
+ "experience": "10 years in blockchain development"
+ },
+ {
+ "name": "Alice Johnson",
+ "role": "Smart Contract Developer",
+ "experience": "5 years Cardano development"
+ }
+ ],
+ "teamCapabilities": "Our team combines deep expertise in DeFi protocols, Cardano development, and system architecture."
+ },
+ "budget": {
+ "totalBudget": 500000,
+ "categories": {
+ "development": 300000,
+ "testing": 100000,
+ "documentation": 50000,
+ "management": 50000
+ },
+ "timeline": {
+ "distributionSchedule": "Quarterly"
+ }
+ },
+ "valueProposition": {
+ "impact": "Accelerate DeFi development on Cardano",
+ "sustainability": "Platform fees and maintenance contracts"
+ }
+ },
+ "mandatoryAcknowledgments": {
+ "fundRules": {
+ "acknowledgment": true
+ },
+ "privacyPolicy": {
+ "acknowledgment": true
+ },
+ "intellectualProperty": {
+ "acknowledgment": true
+ },
+ "compliance": {
+ "legalCompliance": true
+ }
+ }
+}
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/proposalTemplate.F14.schema.json b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/proposalTemplate.F14.schema.json
index 40176e7e832..ce178642c8a 100644
--- a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/proposalTemplate.F14.schema.json
+++ b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/proposalTemplate.F14.schema.json
@@ -364,294 +364,7 @@
}
}
},
- "milestones": {
- "type": "object",
- "title": "Project Milestones",
- "description": "Detailed project milestones and deliverables",
- "properties": {
- "milestonesConfig": {
- "type": "object",
- "title": "Milestones Configuration",
- "description": "Configuration for number of milestones based on grant amount",
- "properties": {
- "grantAmount": {
- "type": "number",
- "title": "Grant Amount in ADA",
- "description": "Total grant amount requested in ADA",
- "minimum": 0,
- "maximum": 1000000
- },
- "numberOfMilestones": {
- "type": "integer",
- "title": "Number of Milestones",
- "description": "Total number of milestones including the final milestone",
- "minimum": 3,
- "maximum": 10
- }
- },
- "required": ["grantAmount", "numberOfMilestones"]
- },
- "milestonesList": {
- "type": "array",
- "title": "List of Milestones",
- "description": "Detailed description of each project milestone",
- "items": {
- "type": "object",
- "title": "Milestone",
- "properties": {
- "title": {
- "type": "string",
- "title": "Milestone Title",
- "description": "Short, descriptive title for the milestone",
- "minLength": 5,
- "maxLength": 100
- },
- "description": {
- "type": "string",
- "title": "Milestone Description",
- "description": "Detailed description of what this milestone entails",
- "minLength": 50,
- "maxLength": 1000
- },
- "deliverables": {
- "type": "array",
- "title": "Deliverables",
- "description": "Specific outputs and deliverables for this milestone",
- "items": {
- "type": "object",
- "properties": {
- "name": {
- "type": "string",
- "title": "Deliverable Name",
- "minLength": 5,
- "maxLength": 100
- },
- "description": {
- "type": "string",
- "title": "Deliverable Description",
- "minLength": 20,
- "maxLength": 500
- },
- "type": {
- "type": "string",
- "title": "Deliverable Type",
- "enum": [
- "Documentation",
- "Software",
- "Report",
- "Presentation",
- "Video",
- "Other"
- ]
- }
- },
- "required": ["name", "description", "type"]
- },
- "minItems": 1,
- "maxItems": 5
- },
- "acceptanceCriteria": {
- "type": "array",
- "title": "Acceptance Criteria",
- "description": "Specific criteria that must be met to consider this milestone complete",
- "items": {
- "type": "string",
- "minLength": 10,
- "maxLength": 200
- },
- "minItems": 1,
- "maxItems": 5
- },
- "evidenceOfCompletion": {
- "type": "array",
- "title": "Evidence of Completion",
- "description": "How will you demonstrate that this milestone is complete?",
- "items": {
- "type": "object",
- "properties": {
- "type": {
- "type": "string",
- "title": "Evidence Type",
- "enum": [
- "Code Repository",
- "Documentation",
- "Demo Video",
- "Test Results",
- "Metrics Report",
- "User Feedback",
- "Other"
- ]
- },
- "description": {
- "type": "string",
- "title": "Evidence Description",
- "minLength": 20,
- "maxLength": 300
- }
- },
- "required": ["type", "description"]
- },
- "minItems": 1,
- "maxItems": 3
- },
- "timeline": {
- "type": "object",
- "title": "Timeline",
- "properties": {
- "startDate": {
- "type": "string",
- "title": "Start Date",
- "format": "date"
- },
- "endDate": {
- "type": "string",
- "title": "End Date",
- "format": "date"
- },
- "durationInWeeks": {
- "type": "integer",
- "title": "Duration in Weeks",
- "minimum": 1,
- "maximum": 52
- }
- },
- "required": ["startDate", "endDate", "durationInWeeks"]
- },
- "budget": {
- "type": "object",
- "title": "Milestone Budget",
- "properties": {
- "amount": {
- "type": "number",
- "title": "Amount in ADA",
- "minimum": 0
- },
- "breakdown": {
- "type": "array",
- "title": "Budget Breakdown",
- "items": {
- "type": "object",
- "properties": {
- "category": {
- "type": "string",
- "enum": [
- "Development",
- "Design",
- "Marketing",
- "Operations",
- "Other"
- ]
- },
- "amount": {
- "type": "number",
- "minimum": 0
- },
- "description": {
- "type": "string",
- "minLength": 10,
- "maxLength": 200
- }
- },
- "required": ["category", "amount", "description"]
- },
- "minItems": 1
- }
- },
- "required": ["amount", "breakdown"]
- }
- },
- "required": [
- "title",
- "description",
- "deliverables",
- "acceptanceCriteria",
- "evidenceOfCompletion",
- "timeline",
- "budget"
- ]
- },
- "minItems": 3,
- "maxItems": 10
- },
- "finalMilestone": {
- "type": "object",
- "title": "Final Milestone",
- "description": "Project close-out milestone with final report and video",
- "properties": {
- "closeoutReport": {
- "type": "object",
- "title": "Project Close-out Report",
- "properties": {
- "summary": {
- "type": "string",
- "title": "Project Summary",
- "description": "Overall summary of project achievements",
- "minLength": 100,
- "maxLength": 2000
- },
- "keyAchievements": {
- "type": "array",
- "title": "Key Achievements",
- "items": {
- "type": "string",
- "minLength": 10,
- "maxLength": 200
- },
- "minItems": 1,
- "maxItems": 10
- },
- "lessonsLearned": {
- "type": "array",
- "title": "Lessons Learned",
- "items": {
- "type": "string",
- "minLength": 20,
- "maxLength": 500
- },
- "minItems": 1,
- "maxItems": 5
- },
- "futureSteps": {
- "type": "string",
- "title": "Future Steps",
- "description": "Plans for project continuation or future development",
- "minLength": 50,
- "maxLength": 1000
- }
- },
- "required": ["summary", "keyAchievements", "lessonsLearned", "futureSteps"]
- },
- "demoVideo": {
- "type": "object",
- "title": "Project Demo Video",
- "properties": {
- "url": {
- "type": "string",
- "title": "Video URL",
- "format": "uri",
- "pattern": "^https://"
- },
- "duration": {
- "type": "integer",
- "title": "Duration in Minutes",
- "minimum": 3,
- "maximum": 15
- },
- "description": {
- "type": "string",
- "title": "Video Description",
- "minLength": 50,
- "maxLength": 500
- }
- },
- "required": ["url", "duration", "description"]
- }
- },
- "required": ["closeoutReport", "demoVideo"]
- }
- },
- "required": ["milestonesConfig", "milestonesList", "finalMilestone"]
- },
+
"Horizons": {
"type": "object",
"title": "Project Horizons",
@@ -917,113 +630,401 @@
"items": {
"type": "object",
"properties": {
- "name": {
- "type": "string",
- "title": "Metric Name",
- "minLength": 5,
- "maxLength": 100
- },
- "description": {
+ "name": {
+ "type": "string",
+ "title": "Metric Name",
+ "minLength": 5,
+ "maxLength": 100
+ },
+ "description": {
+ "type": "string",
+ "title": "Metric Description",
+ "minLength": 20,
+ "maxLength": 300
+ },
+ "target": {
+ "type": "string",
+ "title": "Target Value",
+ "minLength": 1,
+ "maxLength": 100
+ },
+ "measurement": {
+ "type": "string",
+ "title": "Measurement Method",
+ "minLength": 20,
+ "maxLength": 300
+ }
+ },
+ "required": ["name", "description", "target", "measurement"]
+ },
+ "minItems": 2,
+ "maxItems": 5
+ },
+ "outputs": {
+ "type": "array",
+ "title": "Project Outputs",
+ "description": "Tangible outputs and deliverables from the project",
+ "items": {
+ "type": "string",
+ "minLength": 10,
+ "maxLength": 200
+ },
+ "minItems": 1,
+ "maxItems": 10,
+ "uniqueItems": true
+ }
+ },
+ "required": ["communityBenefit", "metrics", "outputs"]
+ },
+ "capability": {
+ "type": "object",
+ "title": "Capability & Feasibility",
+ "description": "Demonstrate your ability to deliver the project successfully",
+ "properties": {
+ "teamExperience": {
+ "type": "string",
+ "title": "Team Experience",
+ "description": "Describe your team's relevant experience and capabilities",
+ "minLength": 100,
+ "maxLength": 1000
+ },
+ "feasibilityApproach": {
+ "type": "string",
+ "title": "Feasibility Approach",
+ "description": "How will you validate the feasibility of your approach?",
+ "minLength": 100,
+ "maxLength": 1000
+ },
+ "riskMitigation": {
+ "type": "array",
+ "title": "Risk Mitigation",
+ "description": "Key risks and mitigation strategies",
+ "items": {
+ "type": "object",
+ "properties": {
+ "risk": {
+ "type": "string",
+ "title": "Risk Description",
+ "minLength": 10,
+ "maxLength": 200
+ },
+ "impact": {
+ "type": "string",
+ "enum": ["Low", "Medium", "High"],
+ "title": "Risk Impact"
+ },
+ "mitigation": {
+ "type": "string",
+ "title": "Mitigation Strategy",
+ "minLength": 20,
+ "maxLength": 300
+ }
+ },
+ "required": ["risk", "impact", "mitigation"]
+ },
+ "minItems": 1,
+ "maxItems": 5
+ },
+ "fundManagement": {
+ "type": "string",
+ "title": "Fund Management",
+ "description": "How will you ensure proper management and accountability of funds?",
+ "minLength": 100,
+ "maxLength": 1000
+ }
+ },
+ "required": ["teamExperience", "feasibilityApproach", "riskMitigation", "fundManagement"]
+ }
+ },
+ "required": ["solution", "impact", "capability"]
+ },
+ "milestones": {
+ "type": "object",
+ "title": "Project Milestones",
+ "description": "Detailed project milestones and deliverables",
+ "properties": {
+ "milestonesConfig": {
+ "type": "object",
+ "title": "Milestones Configuration",
+ "description": "Configuration for number of milestones based on grant amount",
+ "properties": {
+ "grantAmount": {
+ "type": "number",
+ "title": "Grant Amount in ADA",
+ "description": "Total grant amount requested in ADA",
+ "minimum": 0,
+ "maximum": 1000000
+ },
+ "numberOfMilestones": {
+ "type": "integer",
+ "title": "Number of Milestones",
+ "description": "Total number of milestones including the final milestone",
+ "minimum": 3,
+ "maximum": 10
+ }
+ },
+ "required": ["grantAmount", "numberOfMilestones"]
+ },
+ "milestonesList": {
+ "type": "array",
+ "title": "List of Milestones",
+ "description": "Detailed description of each project milestone",
+ "items": {
+ "type": "object",
+ "title": "Milestone",
+ "properties": {
+ "title": {
+ "type": "string",
+ "title": "Milestone Title",
+ "description": "Short, descriptive title for the milestone",
+ "minLength": 5,
+ "maxLength": 100
+ },
+ "description": {
+ "type": "string",
+ "title": "Milestone Description",
+ "description": "Detailed description of what this milestone entails",
+ "minLength": 50,
+ "maxLength": 1000
+ },
+ "deliverables": {
+ "type": "array",
+ "title": "Deliverables",
+ "description": "Specific outputs and deliverables for this milestone",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "title": "Deliverable Name",
+ "minLength": 5,
+ "maxLength": 100
+ },
+ "description": {
+ "type": "string",
+ "title": "Deliverable Description",
+ "minLength": 20,
+ "maxLength": 500
+ },
+ "type": {
+ "type": "string",
+ "title": "Deliverable Type",
+ "enum": [
+ "Documentation",
+ "Software",
+ "Report",
+ "Presentation",
+ "Video",
+ "Other"
+ ]
+ }
+ },
+ "required": ["name", "description", "type"]
+ },
+ "minItems": 1,
+ "maxItems": 5
+ },
+ "acceptanceCriteria": {
+ "type": "array",
+ "title": "Acceptance Criteria",
+ "description": "Specific criteria that must be met to consider this milestone complete",
+ "items": {
+ "type": "string",
+ "minLength": 10,
+ "maxLength": 200
+ },
+ "minItems": 1,
+ "maxItems": 5
+ },
+ "evidenceOfCompletion": {
+ "type": "array",
+ "title": "Evidence of Completion",
+ "description": "How will you demonstrate that this milestone is complete?",
+ "items": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "title": "Evidence Type",
+ "enum": [
+ "Code Repository",
+ "Documentation",
+ "Demo Video",
+ "Test Results",
+ "Metrics Report",
+ "User Feedback",
+ "Other"
+ ]
+ },
+ "description": {
+ "type": "string",
+ "title": "Evidence Description",
+ "minLength": 20,
+ "maxLength": 300
+ }
+ },
+ "required": ["type", "description"]
+ },
+ "minItems": 1,
+ "maxItems": 3
+ },
+ "timeline": {
+ "type": "object",
+ "title": "Timeline",
+ "properties": {
+ "startDate": {
"type": "string",
- "title": "Metric Description",
- "minLength": 20,
- "maxLength": 300
+ "title": "Start Date",
+ "format": "date"
},
- "target": {
+ "endDate": {
"type": "string",
- "title": "Target Value",
- "minLength": 1,
- "maxLength": 100
+ "title": "End Date",
+ "format": "date"
},
- "measurement": {
- "type": "string",
- "title": "Measurement Method",
- "minLength": 20,
- "maxLength": 300
+ "durationInWeeks": {
+ "type": "integer",
+ "title": "Duration in Weeks",
+ "minimum": 1,
+ "maximum": 52
}
},
- "required": ["name", "description", "target", "measurement"]
+ "required": ["startDate", "endDate", "durationInWeeks"]
},
- "minItems": 2,
- "maxItems": 5
+ "budget": {
+ "type": "object",
+ "title": "Milestone Budget",
+ "properties": {
+ "amount": {
+ "type": "number",
+ "title": "Amount in ADA",
+ "minimum": 0
+ },
+ "breakdown": {
+ "type": "array",
+ "title": "Budget Breakdown",
+ "items": {
+ "type": "object",
+ "properties": {
+ "category": {
+ "type": "string",
+ "enum": [
+ "Development",
+ "Design",
+ "Marketing",
+ "Operations",
+ "Other"
+ ]
+ },
+ "amount": {
+ "type": "number",
+ "minimum": 0
+ },
+ "description": {
+ "type": "string",
+ "minLength": 10,
+ "maxLength": 200
+ }
+ },
+ "required": ["category", "amount", "description"]
+ },
+ "minItems": 1
+ }
+ },
+ "required": ["amount", "breakdown"]
+ }
},
- "outputs": {
- "type": "array",
- "title": "Project Outputs",
- "description": "Tangible outputs and deliverables from the project",
- "items": {
- "type": "string",
- "minLength": 10,
- "maxLength": 200
- },
- "minItems": 1,
- "maxItems": 10,
- "uniqueItems": true
- }
+ "required": [
+ "title",
+ "description",
+ "deliverables",
+ "acceptanceCriteria",
+ "evidenceOfCompletion",
+ "timeline",
+ "budget"
+ ]
},
- "required": ["communityBenefit", "metrics", "outputs"]
+ "minItems": 3,
+ "maxItems": 10
},
- "capability": {
+ "finalMilestone": {
"type": "object",
- "title": "Capability & Feasibility",
- "description": "Demonstrate your ability to deliver the project successfully",
+ "title": "Final Milestone",
+ "description": "Project close-out milestone with final report and video",
"properties": {
- "teamExperience": {
- "type": "string",
- "title": "Team Experience",
- "description": "Describe your team's relevant experience and capabilities",
- "minLength": 100,
- "maxLength": 1000
- },
- "feasibilityApproach": {
- "type": "string",
- "title": "Feasibility Approach",
- "description": "How will you validate the feasibility of your approach?",
- "minLength": 100,
- "maxLength": 1000
- },
- "riskMitigation": {
- "type": "array",
- "title": "Risk Mitigation",
- "description": "Key risks and mitigation strategies",
- "items": {
- "type": "object",
- "properties": {
- "risk": {
+ "closeoutReport": {
+ "type": "object",
+ "title": "Project Close-out Report",
+ "properties": {
+ "summary": {
+ "type": "string",
+ "title": "Project Summary",
+ "description": "Overall summary of project achievements",
+ "minLength": 100,
+ "maxLength": 2000
+ },
+ "keyAchievements": {
+ "type": "array",
+ "title": "Key Achievements",
+ "items": {
"type": "string",
- "title": "Risk Description",
"minLength": 10,
"maxLength": 200
},
- "impact": {
- "type": "string",
- "enum": ["Low", "Medium", "High"],
- "title": "Risk Impact"
- },
- "mitigation": {
+ "minItems": 1,
+ "maxItems": 10
+ },
+ "lessonsLearned": {
+ "type": "array",
+ "title": "Lessons Learned",
+ "items": {
"type": "string",
- "title": "Mitigation Strategy",
"minLength": 20,
- "maxLength": 300
- }
+ "maxLength": 500
+ },
+ "minItems": 1,
+ "maxItems": 5
},
- "required": ["risk", "impact", "mitigation"]
+ "futureSteps": {
+ "type": "string",
+ "title": "Future Steps",
+ "description": "Plans for project continuation or future development",
+ "minLength": 50,
+ "maxLength": 1000
+ }
},
- "minItems": 1,
- "maxItems": 5
+ "required": ["summary", "keyAchievements", "lessonsLearned", "futureSteps"]
},
- "fundManagement": {
- "type": "string",
- "title": "Fund Management",
- "description": "How will you ensure proper management and accountability of funds?",
- "minLength": 100,
- "maxLength": 1000
+ "demoVideo": {
+ "type": "object",
+ "title": "Project Demo Video",
+ "properties": {
+ "url": {
+ "type": "string",
+ "title": "Video URL",
+ "format": "uri",
+ "pattern": "^https://"
+ },
+ "duration": {
+ "type": "integer",
+ "title": "Duration in Minutes",
+ "minimum": 3,
+ "maximum": 15
+ },
+ "description": {
+ "type": "string",
+ "title": "Video Description",
+ "minLength": 50,
+ "maxLength": 500
+ }
+ },
+ "required": ["url", "duration", "description"]
}
},
- "required": ["teamExperience", "feasibilityApproach", "riskMitigation", "fundManagement"]
+ "required": ["closeoutReport", "demoVideo"]
}
},
- "required": ["solution", "impact", "capability"]
+ "required": ["milestonesConfig", "milestonesList", "finalMilestone"]
},
"finalPitch": {
"type": "object",
@@ -1350,13 +1351,16 @@
"type": "string",
"title": "Fund Rules Version",
"description": "Version of the Fund Rules being acknowledged",
- "pattern": "^F[0-9]+$"
+ "pattern": "^F[0-9]{1,3}$",
+ "examples": ["F14", "F15"]
},
"timestamp": {
"type": "string",
"title": "Acknowledgment Timestamp",
"description": "When the rules were acknowledged",
- "format": "date-time"
+ "format": "date-time",
+ "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]+)?(Z|[+-][0-9]{2}:[0-9]{2})$",
+ "examples": ["2024-01-20T15:30:00Z"]
}
},
"required": ["acknowledgment", "version", "timestamp"]
@@ -1375,16 +1379,27 @@
"type": "string",
"title": "Terms Version",
"description": "Version of the Terms and Conditions being acknowledged",
- "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$",
+ "examples": ["1.0.0", "2.1.3"]
+ },
+ "documentUrl": {
+ "type": "string",
+ "title": "Terms Document URL",
+ "description": "URL to the specific version of terms and conditions",
+ "format": "uri",
+ "pattern": "^https://[\\w\\-\\.]+\\.[a-zA-Z]{2,}/.*$",
+ "contentMediaType": "text/html"
},
"timestamp": {
"type": "string",
"title": "Acknowledgment Timestamp",
"description": "When the terms were acknowledged",
- "format": "date-time"
+ "format": "date-time",
+ "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]+)?(Z|[+-][0-9]{2}:[0-9]{2})$",
+ "examples": ["2024-01-20T15:30:00Z"]
}
},
- "required": ["acknowledgment", "version", "timestamp"]
+ "required": ["acknowledgment", "version", "timestamp", "documentUrl"]
},
"privacyPolicy": {
"type": "object",
@@ -1400,16 +1415,27 @@
"type": "string",
"title": "Privacy Policy Version",
"description": "Version of the Privacy Policy being acknowledged",
- "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$",
+ "examples": ["1.0.0", "2.1.3"]
+ },
+ "documentUrl": {
+ "type": "string",
+ "title": "Privacy Policy URL",
+ "description": "URL to the specific version of privacy policy",
+ "format": "uri",
+ "pattern": "^https://[\\w\\-\\.]+\\.[a-zA-Z]{2,}/.*$",
+ "contentMediaType": "text/html"
},
"timestamp": {
"type": "string",
"title": "Acknowledgment Timestamp",
"description": "When the privacy policy was acknowledged",
- "format": "date-time"
+ "format": "date-time",
+ "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]+)?(Z|[+-][0-9]{2}:[0-9]{2})$",
+ "examples": ["2024-01-20T15:30:00Z"]
}
},
- "required": ["acknowledgment", "version", "timestamp"]
+ "required": ["acknowledgment", "version", "timestamp", "documentUrl"]
},
"intellectualProperty": {
"type": "object",
@@ -1425,13 +1451,46 @@
"type": "string",
"title": "IP Details",
"description": "Additional details about intellectual property rights (if applicable)",
- "maxLength": 1000
+ "maxLength": 1000,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
+ },
+ "attachments": {
+ "type": "array",
+ "title": "IP Documentation",
+ "description": "Supporting documentation for IP rights (if applicable)",
+ "items": {
+ "type": "object",
+ "properties": {
+ "documentType": {
+ "type": "string",
+ "enum": ["patent", "trademark", "copyright", "license", "other"],
+ "description": "Type of IP documentation"
+ },
+ "documentUrl": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https://[\\w\\-\\.]+\\.[a-zA-Z]{2,}/.*$",
+ "contentMediaType": "application/pdf"
+ },
+ "description": {
+ "type": "string",
+ "maxLength": 500,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
+ }
+ },
+ "required": ["documentType", "documentUrl", "description"]
+ },
+ "maxItems": 10
},
"timestamp": {
"type": "string",
"title": "Acknowledgment Timestamp",
"description": "When the IP declaration was made",
- "format": "date-time"
+ "format": "date-time",
+ "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]+)?(Z|[+-][0-9]{2}:[0-9]{2})$",
+ "examples": ["2024-01-20T15:30:00Z"]
}
},
"required": ["acknowledgment", "timestamp"]
@@ -1458,14 +1517,28 @@
"description": "I confirm that all information provided is accurate and complete",
"const": true
},
+ "jurisdictions": {
+ "type": "array",
+ "title": "Applicable Jurisdictions",
+ "description": "List of jurisdictions where compliance is declared",
+ "items": {
+ "type": "string",
+ "pattern": "^[A-Z]{2}$",
+ "description": "ISO 3166-1 alpha-2 country code"
+ },
+ "minItems": 1,
+ "uniqueItems": true
+ },
"timestamp": {
"type": "string",
"title": "Acknowledgment Timestamp",
"description": "When the compliance declaration was made",
- "format": "date-time"
+ "format": "date-time",
+ "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]+)?(Z|[+-][0-9]{2}:[0-9]{2})$",
+ "examples": ["2024-01-20T15:30:00Z"]
}
},
- "required": ["legalCompliance", "noConflictOfInterest", "accurateInformation", "timestamp"]
+ "required": ["legalCompliance", "noConflictOfInterest", "accurateInformation", "jurisdictions", "timestamp"]
},
"additionalAcknowledgments": {
"type": "array",
@@ -1478,7 +1551,8 @@
"type": "string",
"title": "Acknowledgment Type",
"minLength": 5,
- "maxLength": 100
+ "maxLength": 100,
+ "pattern": "^[a-zA-Z][a-zA-Z0-9_\\-\\.]*$"
},
"acknowledgment": {
"type": "boolean",
@@ -1490,12 +1564,24 @@
"title": "Description",
"description": "Detailed description of what is being acknowledged",
"minLength": 10,
- "maxLength": 500
+ "maxLength": 500,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
+ },
+ "documentUrl": {
+ "type": "string",
+ "title": "Reference Document",
+ "description": "URL to the document being acknowledged",
+ "format": "uri",
+ "pattern": "^https://[\\w\\-\\.]+\\.[a-zA-Z]{2,}/.*$",
+ "contentMediaType": "text/html"
},
"timestamp": {
"type": "string",
"title": "Acknowledgment Timestamp",
- "format": "date-time"
+ "format": "date-time",
+ "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]+)?(Z|[+-][0-9]{2}:[0-9]{2})$",
+ "examples": ["2024-01-20T15:30:00Z"]
}
},
"required": ["type", "acknowledgment", "description", "timestamp"]
From 057ec964d2cf2968e25721cda5232ea9865e849b Mon Sep 17 00:00:00 2001
From: Nathan Bogale
Date: Wed, 4 Dec 2024 22:27:40 +0300
Subject: [PATCH 05/25] fix(cat-gateway): added better pattern per schema
section of f14 template
---
.../proposalTemplate.F14.schema.json | 286 +++++++++++++-----
1 file changed, 211 insertions(+), 75 deletions(-)
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/proposalTemplate.F14.schema.json b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/proposalTemplate.F14.schema.json
index ce178642c8a..5cf34a23aae 100644
--- a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/proposalTemplate.F14.schema.json
+++ b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/proposalTemplate.F14.schema.json
@@ -28,7 +28,9 @@
"description": "A clear, unambiguous, and concise title for your proposal",
"minLength": 1,
"maxLength": 60,
- "examples": ["DeFi Integration Platform for Cardano"]
+ "examples": ["DeFi Integration Platform for Cardano"],
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
}
},
"additionalProperties": false,
@@ -45,7 +47,9 @@
"description": "Name and surname of main applicant",
"$comment": "Please provide the name and surname of the main applicant. The main applicant is considered as the individual responsible for the project and the person authorized to act on behalf of other applicants (where applicable).",
"minLength": 2,
- "maxLength": 100
+ "maxLength": 100,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"applicant_type": {
"type": "string",
@@ -98,7 +102,7 @@
}
}
},
- "Time": {
+ "time": {
"type": "object",
"properties": {
"project_duration": {
@@ -112,7 +116,7 @@
},
"required": ["project_duration"]
},
- "Translation": {
+ "translation": {
"type": "object",
"title": "Translation Information",
"description": "Information about the proposal's language and translation status",
@@ -129,13 +133,17 @@
"description": "If auto-translated, specify the original language of your proposal",
"minLength": 2,
"maxLength": 50,
- "examples": ["Spanish", "Japanese", "French"]
+ "examples": ["Spanish", "Japanese", "French"],
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"translationNotes": {
"type": "string",
"title": "Translation Notes",
"description": "Additional notes about the translation or original language content",
- "maxLength": 500
+ "maxLength": 500,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
}
},
"required": ["isTranslated"],
@@ -150,7 +158,7 @@
"required": ["originalLanguage"]
}
},
- "Problem": {
+ "problem": {
"type": "object",
"title": "Problem Statement",
"description": "Define the problem your proposal aims to solve",
@@ -161,7 +169,9 @@
"description": "Clearly define the problem you aim to solve. This will be visible in the Catalyst voting app.",
"minLength": 10,
"maxLength": 200,
- "examples": ["The Cardano ecosystem lacks standardized tools for cross-protocol communication, resulting in fragmented user experiences and inefficient resource utilization."]
+ "examples": ["The Cardano ecosystem lacks standardized tools for cross-protocol communication, resulting in fragmented user experiences and inefficient resource utilization."],
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"impactArea": {
"type": "array",
@@ -189,7 +199,7 @@
},
"required": ["statement", "impactArea"]
},
- "Solution": {
+ "solution": {
"type": "object",
"title": "Solution Overview",
"description": "Describe your proposed solution to the problem",
@@ -200,13 +210,17 @@
"description": "Briefly describe your solution. Focus on what you will do or create to solve the problem.",
"minLength": 10,
"maxLength": 200,
- "examples": ["Develop an open-source integration framework that standardizes protocol communication and provides a unified API layer for seamless DeFi interactions."]
+ "examples": ["Develop an open-source integration framework that standardizes protocol communication and provides a unified API layer for seamless DeFi interactions."],
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"approach": {
"type": "string",
"title": "Technical Approach",
"description": "Outline the technical approach or methodology you will use",
- "maxLength": 500
+ "maxLength": 500,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"innovationAspects": {
"type": "array",
@@ -214,7 +228,9 @@
"description": "Key innovative aspects of your solution",
"items": {
"type": "string",
- "maxLength": 100
+ "maxLength": 100,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"minItems": 1,
"maxItems": 5,
@@ -244,7 +260,9 @@
"examples": [
"https://github.com/your-org/project",
"https://your-project-docs.com"
- ]
+ ],
+ "pattern": "^https?://[\\w\\-]+(\\.[\\w\\-]+)+[/#?]?.*$",
+ "contentMediaType": "text/uri-list"
},
"type": {
"type": "string",
@@ -271,7 +289,9 @@
"examples": [
"Project's main GitHub repository containing all source code",
"Technical whitepaper detailing the solution architecture"
- ]
+ ],
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
}
},
"required": ["url", "type", "description"]
@@ -285,18 +305,22 @@
"format": "uri",
"pattern": "^https://(github\\.com|gitlab\\.com|bitbucket\\.org)/.*",
"title": "Main Code Repository",
- "description": "Primary repository where the project's code will be hosted"
+ "description": "Primary repository where the project's code will be hosted",
+ "pattern": "^https?://[\\w\\-]+(\\.[\\w\\-]+)+[/#?]?.*$",
+ "contentMediaType": "text/uri-list"
},
"documentation": {
"type": "string",
"format": "uri",
"pattern": "^https://.*",
"title": "Documentation URL",
- "description": "Main documentation site or resource for the project"
+ "description": "Main documentation site or resource for the project",
+ "pattern": "^https?://[\\w\\-]+(\\.[\\w\\-]+)+[/#?]?.*$",
+ "contentMediaType": "text/uri-list"
}
}
},
- "Dependencies": {
+ "dependencies": {
"type": "object",
"title": "Project Dependencies",
"description": "External dependencies and requirements for project success",
@@ -318,7 +342,9 @@
"type": "string",
"title": "Dependency Name",
"description": "Name of the organization, technology, or resource",
- "maxLength": 100
+ "maxLength": 100,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"type": {
"type": "string",
@@ -336,13 +362,17 @@
"type": "string",
"title": "Description",
"description": "Explain why this dependency is essential and how it affects your project",
- "maxLength": 500
+ "maxLength": 500,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"mitigationPlan": {
"type": "string",
"title": "Mitigation Plan",
"description": "How will you handle potential issues with this dependency",
- "maxLength": 300
+ "maxLength": 300,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
}
},
"required": ["name", "type", "description"]
@@ -365,7 +395,7 @@
}
},
- "Horizons": {
+ "horizons": {
"type": "object",
"title": "Project Horizons",
"description": "Long-term vision and categorization of your project",
@@ -493,7 +523,9 @@
"items": {
"type": "string",
"minLength": 2,
- "maxLength": 30
+ "maxLength": 30,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"minItems": 1,
"maxItems": 5,
@@ -535,19 +567,25 @@
"type": "string",
"title": "Metric Name",
"description": "Name of the metric",
- "maxLength": 100
+ "maxLength": 100,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"target": {
"type": "string",
"title": "Target Value",
"description": "Target value or goal for this metric",
- "maxLength": 100
+ "maxLength": 100,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"measurement": {
"type": "string",
"title": "Measurement Method",
"description": "How this metric will be measured",
- "maxLength": 200
+ "maxLength": 200,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
}
},
"required": ["metric", "target", "measurement"]
@@ -579,14 +617,18 @@
"maxLength": 2000,
"examples": [
"Our solution involves developing a decentralized education platform that will..."
- ]
+ ],
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"uniqueValue": {
"type": "string",
"title": "Unique Value Proposition",
"description": "What makes your solution unique and innovative?",
"minLength": 50,
- "maxLength": 500
+ "maxLength": 500,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"targetAudience": {
"type": "array",
@@ -595,7 +637,9 @@
"items": {
"type": "string",
"minLength": 5,
- "maxLength": 100
+ "maxLength": 100,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"minItems": 1,
"maxItems": 5,
@@ -606,7 +650,9 @@
"title": "Implementation Approach",
"description": "How will you implement your solution?",
"minLength": 100,
- "maxLength": 1000
+ "maxLength": 1000,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
}
},
"required": ["description", "uniqueValue", "targetAudience", "implementation"]
@@ -621,7 +667,9 @@
"title": "Community Benefit",
"description": "How will the Cardano community benefit from your project?",
"minLength": 100,
- "maxLength": 1000
+ "maxLength": 1000,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"metrics": {
"type": "array",
@@ -634,25 +682,33 @@
"type": "string",
"title": "Metric Name",
"minLength": 5,
- "maxLength": 100
+ "maxLength": 100,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"description": {
"type": "string",
"title": "Metric Description",
"minLength": 20,
- "maxLength": 300
+ "maxLength": 300,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"target": {
"type": "string",
"title": "Target Value",
"minLength": 1,
- "maxLength": 100
+ "maxLength": 100,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"measurement": {
"type": "string",
"title": "Measurement Method",
"minLength": 20,
- "maxLength": 300
+ "maxLength": 300,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
}
},
"required": ["name", "description", "target", "measurement"]
@@ -667,7 +723,9 @@
"items": {
"type": "string",
"minLength": 10,
- "maxLength": 200
+ "maxLength": 200,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"minItems": 1,
"maxItems": 10,
@@ -686,14 +744,18 @@
"title": "Team Experience",
"description": "Describe your team's relevant experience and capabilities",
"minLength": 100,
- "maxLength": 1000
+ "maxLength": 1000,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"feasibilityApproach": {
"type": "string",
"title": "Feasibility Approach",
"description": "How will you validate the feasibility of your approach?",
"minLength": 100,
- "maxLength": 1000
+ "maxLength": 1000,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"riskMitigation": {
"type": "array",
@@ -706,7 +768,9 @@
"type": "string",
"title": "Risk Description",
"minLength": 10,
- "maxLength": 200
+ "maxLength": 200,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"impact": {
"type": "string",
@@ -717,7 +781,9 @@
"type": "string",
"title": "Mitigation Strategy",
"minLength": 20,
- "maxLength": 300
+ "maxLength": 300,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
}
},
"required": ["risk", "impact", "mitigation"]
@@ -730,7 +796,9 @@
"title": "Fund Management",
"description": "How will you ensure proper management and accountability of funds?",
"minLength": 100,
- "maxLength": 1000
+ "maxLength": 1000,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
}
},
"required": ["teamExperience", "feasibilityApproach", "riskMitigation", "fundManagement"]
@@ -746,7 +814,7 @@
"milestonesConfig": {
"type": "object",
"title": "Milestones Configuration",
- "description": "Configuration for number of milestones based on grant amount",
+ "description": "Configuration for number of milestones",
"properties": {
"grantAmount": {
"type": "number",
@@ -778,14 +846,18 @@
"title": "Milestone Title",
"description": "Short, descriptive title for the milestone",
"minLength": 5,
- "maxLength": 100
+ "maxLength": 100,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"description": {
"type": "string",
"title": "Milestone Description",
"description": "Detailed description of what this milestone entails",
"minLength": 50,
- "maxLength": 1000
+ "maxLength": 1000,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"deliverables": {
"type": "array",
@@ -798,13 +870,17 @@
"type": "string",
"title": "Deliverable Name",
"minLength": 5,
- "maxLength": 100
+ "maxLength": 100,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"description": {
"type": "string",
"title": "Deliverable Description",
"minLength": 20,
- "maxLength": 500
+ "maxLength": 500,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"type": {
"type": "string",
@@ -831,7 +907,9 @@
"items": {
"type": "string",
"minLength": 10,
- "maxLength": 200
+ "maxLength": 200,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"minItems": 1,
"maxItems": 5
@@ -860,7 +938,9 @@
"type": "string",
"title": "Evidence Description",
"minLength": 20,
- "maxLength": 300
+ "maxLength": 300,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
}
},
"required": ["type", "description"]
@@ -923,7 +1003,9 @@
"description": {
"type": "string",
"minLength": 10,
- "maxLength": 200
+ "maxLength": 200,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
}
},
"required": ["category", "amount", "description"]
@@ -961,7 +1043,9 @@
"title": "Project Summary",
"description": "Overall summary of project achievements",
"minLength": 100,
- "maxLength": 2000
+ "maxLength": 2000,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"keyAchievements": {
"type": "array",
@@ -969,7 +1053,9 @@
"items": {
"type": "string",
"minLength": 10,
- "maxLength": 200
+ "maxLength": 200,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"minItems": 1,
"maxItems": 10
@@ -980,7 +1066,9 @@
"items": {
"type": "string",
"minLength": 20,
- "maxLength": 500
+ "maxLength": 500,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"minItems": 1,
"maxItems": 5
@@ -990,7 +1078,9 @@
"title": "Future Steps",
"description": "Plans for project continuation or future development",
"minLength": 50,
- "maxLength": 1000
+ "maxLength": 1000,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
}
},
"required": ["summary", "keyAchievements", "lessonsLearned", "futureSteps"]
@@ -1003,7 +1093,9 @@
"type": "string",
"title": "Video URL",
"format": "uri",
- "pattern": "^https://"
+ "pattern": "^https://",
+ "pattern": "^https?://[\\w\\-]+(\\.[\\w\\-]+)+[/#?]?.*$",
+ "contentMediaType": "text/uri-list"
},
"duration": {
"type": "integer",
@@ -1015,7 +1107,9 @@
"type": "string",
"title": "Video Description",
"minLength": 50,
- "maxLength": 500
+ "maxLength": 500,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
}
},
"required": ["url", "duration", "description"]
@@ -1048,14 +1142,18 @@
"title": "Name",
"description": "Full name of the team member",
"minLength": 2,
- "maxLength": 100
+ "maxLength": 100,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"role": {
"type": "string",
"title": "Role",
"description": "Primary role in the project",
"minLength": 5,
- "maxLength": 100
+ "maxLength": 100,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"expertise": {
"type": "array",
@@ -1063,7 +1161,9 @@
"items": {
"type": "string",
"minLength": 3,
- "maxLength": 50
+ "maxLength": 50,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"minItems": 1,
"maxItems": 5,
@@ -1074,7 +1174,9 @@
"title": "Relevant Experience",
"description": "Brief description of relevant experience",
"minLength": 50,
- "maxLength": 500
+ "maxLength": 500,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"links": {
"type": "array",
@@ -1097,11 +1199,15 @@
"url": {
"type": "string",
"format": "uri",
- "pattern": "^https://"
+ "pattern": "^https://",
+ "pattern": "^https?://[\\w\\-]+(\\.[\\w\\-]+)+[/#?]?.*$",
+ "contentMediaType": "text/uri-list"
},
"description": {
"type": "string",
- "maxLength": 100
+ "maxLength": 100,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
}
},
"required": ["type", "url"]
@@ -1119,7 +1225,9 @@
"title": "Team Capabilities",
"description": "Overview of the team's collective capabilities and why they are best suited for this project",
"minLength": 100,
- "maxLength": 1000
+ "maxLength": 1000,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"previousWork": {
"type": "array",
@@ -1132,25 +1240,33 @@
"type": "string",
"title": "Project Name",
"minLength": 3,
- "maxLength": 100
+ "maxLength": 100,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"description": {
"type": "string",
"title": "Project Description",
"minLength": 50,
- "maxLength": 500
+ "maxLength": 500,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"relevance": {
"type": "string",
"title": "Relevance to Current Proposal",
"minLength": 50,
- "maxLength": 300
+ "maxLength": 300,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"url": {
"type": "string",
"title": "Project URL",
"format": "uri",
- "pattern": "^https://"
+ "pattern": "^https://",
+ "pattern": "^https?://[\\w\\-]+(\\.[\\w\\-]+)+[/#?]?.*$",
+ "contentMediaType": "text/uri-list"
}
},
"required": ["projectName", "description", "relevance"]
@@ -1199,7 +1315,9 @@
"description": {
"type": "string",
"minLength": 20,
- "maxLength": 300
+ "maxLength": 300,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"breakdown": {
"type": "array",
@@ -1209,7 +1327,9 @@
"item": {
"type": "string",
"minLength": 5,
- "maxLength": 100
+ "maxLength": 100,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"cost": {
"type": "number",
@@ -1218,7 +1338,9 @@
"justification": {
"type": "string",
"minLength": 20,
- "maxLength": 200
+ "maxLength": 200,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
}
},
"required": ["item", "cost", "justification"]
@@ -1242,7 +1364,9 @@
"milestone": {
"type": "string",
"minLength": 5,
- "maxLength": 100
+ "maxLength": 100,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"amount": {
"type": "number",
@@ -1274,7 +1398,9 @@
"title": "Cost-Benefit Analysis",
"description": "Analysis of the project's costs versus its benefits to the Cardano ecosystem",
"minLength": 100,
- "maxLength": 1000
+ "maxLength": 1000,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"impactMetrics": {
"type": "array",
@@ -1287,19 +1413,25 @@
"type": "string",
"title": "Metric Name",
"minLength": 5,
- "maxLength": 100
+ "maxLength": 100,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"target": {
"type": "string",
"title": "Target Value",
"minLength": 1,
- "maxLength": 100
+ "maxLength": 100,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"justification": {
"type": "string",
"title": "Value Justification",
"minLength": 50,
- "maxLength": 300
+ "maxLength": 300,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
}
},
"required": ["metric", "target", "justification"]
@@ -1312,7 +1444,9 @@
"title": "Long-term Value",
"description": "Description of the long-term value and sustainability of the project",
"minLength": 100,
- "maxLength": 1000
+ "maxLength": 1000,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"communityBenefits": {
"type": "array",
@@ -1321,7 +1455,9 @@
"items": {
"type": "string",
"minLength": 20,
- "maxLength": 200
+ "maxLength": 200,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
},
"minItems": 2,
"maxItems": 5
From 68cb23b48f47923c483325b82bcda1bf5fe4b7b5 Mon Sep 17 00:00:00 2001
From: Nathan Bogale
Date: Wed, 4 Dec 2024 22:44:17 +0300
Subject: [PATCH 06/25] fix(cat-gateway): json types and syntax update
---
.../F14-Generic/example.proposal.json | 6 +-
.../proposalTemplate.F14.schema.json | 157 ++++++++----------
2 files changed, 69 insertions(+), 94 deletions(-)
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/example.proposal.json b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/example.proposal.json
index bd5def1aaa7..6c1318570dd 100644
--- a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/example.proposal.json
+++ b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/example.proposal.json
@@ -6,8 +6,8 @@
},
"proposer": {
"mainApplicant": "John Smith",
- "applicant_type": "Entity (Incorporated)",
- "co-proposers": ["Alice Johnson", "Bob Wilson"]
+ "applicantType": "Entity (Incorporated)",
+ "coProposers": ["Alice Johnson", "Bob Wilson"]
}
},
"proposalSummary": {
@@ -27,7 +27,7 @@
"horizons": {
"category": {
"primaryCategory": "DeFi",
- "subCategory": "Integration Tools"
+ "subCategory": "Developer Tools"
},
"tags": ["defi", "integration", "developer-tools", "smart-contracts"]
},
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/proposalTemplate.F14.schema.json b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/proposalTemplate.F14.schema.json
index 5cf34a23aae..2f75889e10a 100644
--- a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/proposalTemplate.F14.schema.json
+++ b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/proposalTemplate.F14.schema.json
@@ -51,7 +51,7 @@
"pattern": "^[\\S\\s]*$",
"contentMediaType": "text/plain"
},
- "applicant_type": {
+ "applicantType": {
"type": "string",
"title": "Are you delivering this project as an individual or as an entity (whether formally incorporated or not)",
"description": "Are you delivering this project as an individual or as an entity (whether formally incorporated or not)",
@@ -62,8 +62,8 @@
"Entity (Not Incorporated)"
]
},
- "co-proposers": {
- "type": "string",
+ "coProposers": {
+ "type": "array",
"title": "Co-proposers and additional applicants",
"description": "Co-proposers and additional applicants",
"$comment": "List any persons who are submitting the proposal jointly with the main applicant. Make sure you have confirmed approval/awareness with these individuals/accounts before adding them. If there is more than one proposer, identify the lead person who is authorized to act on behalf of other co-proposers. IMPORTANT A maximum of 6 (six) proposals can be led or co-proposed by the same applicant or enterprise. Please, reference Fund 13 rules for added detail.",
@@ -105,7 +105,7 @@
"time": {
"type": "object",
"properties": {
- "project_duration": {
+ "projectDuration": {
"type": "integer",
"title": "Project Duration in Months",
"description": "Specify the expected duration of your project. Projects must be completable within 2-12 months.",
@@ -114,7 +114,7 @@
"examples": ["Minimum 2 months-Maximum 12 months. The scope of your funding request and this project is expected to produce the deliverables you specify in the proposal within 2-12 months If you believe your project will take longer than 12 months, consider reducing the project's scope so that it becomes achievable within 12 months If your project completes earlier than scheduled so long as you have submitted your PoAs and Project Close-out report and video then your project can be closed out."]
}
},
- "required": ["project_duration"]
+ "required": ["projectDuration"]
},
"translation": {
"type": "object",
@@ -428,91 +428,67 @@
"type": "string",
"title": "Sub-category",
"description": "Specific area within the main category",
- "enum": {
- "Governance": [
- "DAO",
- "Voting",
- "Treasury Management"
- ],
- "Education": [
- "Learn to Earn",
- "Training",
- "Translation"
- ],
- "Community & Outreach": [
- "Connected Community",
- "Social Media",
- "Community Building"
- ],
- "Development & Tools": [
- "Developer Tools",
- "L2 Infrastructure",
- "Analytics",
- "AI Research",
- "UTXO",
- "P2P"
- ],
- "Identity & Security": [
- "Identity & Verification",
- "Cybersecurity",
- "Authentication",
- "Privacy"
- ],
- "DeFi": [
- "Payments",
- "Stablecoin",
- "Risk Management",
- "Yield",
- "Staking",
- "Lending"
- ],
- "Real World Applications": [
- "Wallet",
- "Marketplace",
- "Manufacturing",
- "IoT",
- "Financial Services",
- "E-commerce",
- "Business Services",
- "Supply Chain",
- "Real Estate",
- "Healthcare",
- "Tourism",
- "Entertainment",
- "RWA",
- "Music",
- "Tokenization"
- ],
- "Events & Marketing": [
- "Events",
- "Marketing",
- "Hackathons",
- "Accelerator",
- "Incubator"
- ],
- "Interoperability": [
- "Cross-chain",
- "Off-chain",
- "Bridges"
- ],
- "Legal & Policy": [
- "Policy",
- "Advocacy",
- "Standards",
- "Compliance"
- ],
- "Sustainability": [
- "Environment",
- "Agriculture",
- "Clean Energy"
- ],
- "Smart Contracts": [
- "Development",
- "Security",
- "Templates",
- "Auditing"
- ]
- }
+ "enum": [
+ "DAO",
+ "Voting",
+ "Treasury Management",
+ "Learn to Earn",
+ "Training",
+ "Translation",
+ "Connected Community",
+ "Social Media",
+ "Community Building",
+ "Developer Tools",
+ "L2 Infrastructure",
+ "Analytics",
+ "AI Research",
+ "UTXO",
+ "P2P",
+ "Identity & Verification",
+ "Cybersecurity",
+ "Authentication",
+ "Privacy",
+ "Payments",
+ "Stablecoin",
+ "Risk Management",
+ "Yield",
+ "Staking",
+ "Lending",
+ "Wallet",
+ "Marketplace",
+ "Manufacturing",
+ "IoT",
+ "Financial Services",
+ "E-commerce",
+ "Business Services",
+ "Supply Chain",
+ "Real Estate",
+ "Healthcare",
+ "Tourism",
+ "Entertainment",
+ "RWA",
+ "Music",
+ "Tokenization",
+ "Events",
+ "Marketing",
+ "Hackathons",
+ "Accelerator",
+ "Incubator",
+ "Cross-chain",
+ "Off-chain",
+ "Bridges",
+ "Policy",
+ "Advocacy",
+ "Standards",
+ "Compliance",
+ "Environment",
+ "Agriculture",
+ "Clean Energy",
+ "Development",
+ "Security",
+ "Templates",
+ "Auditing"
+ ]
}
}
},
@@ -884,7 +860,6 @@
},
"type": {
"type": "string",
- "title": "Deliverable Type",
"enum": [
"Documentation",
"Software",
From 4efb65c36629869e27035ee14f227e491a3ee5d6 Mon Sep 17 00:00:00 2001
From: Steven Johnson
Date: Thu, 5 Dec 2024 12:10:50 +0700
Subject: [PATCH 07/25] docs(cat-gateway): add example of common field types to
help UI render
---
...38-9258-4fbc-a62e-7faa6e58318f.schema.json | 152 ++++++++++--------
.../F14-Generic/proposal.F14.example.json | 6 +-
2 files changed, 88 insertions(+), 70 deletions(-)
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
index 07bcf365c27..63abfbcede2 100644
--- a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
+++ b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
@@ -2,6 +2,55 @@
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Catalyst Fund 14 Base Proposal Template",
"description": "A structured template for creating Fund 14 proposals",
+ "definitions": {
+ "singleLineTextEntry": {
+ "type": "string",
+ "contentMediaType": "text/plain",
+ "pattern": "^.*$"
+ },
+ "multiLineTextEntry": {
+ "type": "string",
+ "contentMediaType": "text/plain",
+ "pattern": "^[\\S\\s]$"
+ },
+ "dropDownSingleSelect": {
+ "type": "string",
+ "contentMediaType": "text/plain",
+ "pattern": "^.*$",
+ "format": "dropDownSingleSelect"
+ },
+ "tokenValueCardanoADA": {
+ "type": "integer",
+ "format": "token:cardano:ada"
+ },
+ "durationInMonths": {
+ "type": "integer",
+ "format": "datetime:duration:months"
+ },
+ "agreementConfirmation": {
+ "type": "boolean",
+ "format": "checkbox",
+ "default": false,
+ "const": true
+ },
+ "yesNoChoice": {
+ "type": "boolean",
+ "format": "yes/no",
+ "default": false
+ },
+ "uriList": {
+ "type": "array",
+ "format": "uriList",
+ "uniqueItems": true,
+ "default": [],
+ "items": {
+ "type": "string",
+ "format": "uri",
+ "contentMediaType": "text/plain",
+ "maxLength": 1024
+ }
+ }
+ },
"type": "object",
"properties": {
"$schema": {
@@ -14,41 +63,23 @@
"type": "object",
"properties": {
"title": {
- "type": "string",
+ "$ref": "#/definitions/singleLineTextEntry",
"title": "Proposal title",
"description": "Please note we suggest you use no more than 60 characters for your proposal title so that it can be easily viewed in the voting app.
The title should clearly express what the proposal is about. Voters can see the title in the voting app, even without opening the proposal, so a clear, unambiguous, and concise title is very important.
",
- "contentMediaType": "text/plain",
- "pattern": "^.*$",
"maxLength": 80,
"minLength": 0
},
- {
- "email": {
- "type": "string",
- "title": "Email",
- "description": "Please provide the name and surname of the main applicant. The main applicant is considered as the individual responsible for the project and the person authorized to act on behalf of other applicants (where applicable).
",
- "contentMediaType": "text/plain",
- "format": "email",
- "pattern": "^.*$",
- "maxLength": 80,
- "minLength": 0
- },
-
- },
"applicant": {
- "type": "string",
+ "$ref": "#/definitions/singleLineTextEntry",
"title": "Name and surname of main applicant",
"description": "Please provide the name and surname of the main applicant. The main applicant is considered as the individual responsible for the project and the person authorized to act on behalf of other applicants (where applicable).
",
- "contentMediaType": "text/plain",
- "pattern": "^.*$",
"maxLength": 80,
"minLength": 0
},
"applicant_type": {
- "type": "string",
+ "$ref": "#/definitions/dropDownSingleSelect",
"title": "Are you delivering this project as an individual or as an entity (whether formally incorporated or not)",
"description": "Please select from one of the following:
",
- "contentMediaType": "text/plain",
"enum": [
"Individual",
"Entity (Incorporated)",
@@ -57,90 +88,68 @@
"default": "Individual"
},
"co-proposers": {
- "type": "string",
+ "$ref": "#/definitions/multiLineTextEntry",
"title": "Co-proposers and additional applicants",
"description": "List any persons who are submitting the proposal jointly with the main applicant. Make sure you have confirmed approval/awareness with these individuals / accounts before adding them. If there is more than one proposer, identify the lead person who is authorized to act on behalf of other co-proposers.
IMPORTANT - A maximum of 6 (six) proposals can be led or co-proposed by the same applicant or enterprise. Please, reference Fund13 rules for added detail.
",
- "contentMediaType": "text/plain",
- "pattern": "^[\\S\\s]$",
"maxLength": 1024,
"minLength": 0
},
"requested_funds": {
- "type": "integer",
+ "$ref": "#/definitions/tokenValueCardanoADA",
"title": "Requested funds in ada",
"description": "There is a minimum and a maximum amount of funding that can be requested in a single Catalyst proposal. These are outlined below per each category:
Minimum Funding Amount per proposal:
- Cardano Open: ₳15,000
- Cardano Uses Cases: ₳15,000
- Cardano Partners: ₳500,000
Maximum Funding Amount per proposal:
- Cardano Open:
- Developers (technical): ₳200,000
- Ecosystem (non-technical): ₳100,000
- Cardano Uses Cases:
- Concept: ₳150,000
- Product: ₳500,000
- Cardano Partners:
- Enterprise R&D: ₳2,000,000
- Growth & Acceleration: ₳2,000,000
",
"minimum": 1,
- "maximum": 18446744073709551615,
- "format": "cardano:ada"
+ "maximum": 18446744073709551615
},
"duration": {
- "type": "integer",
+ "$ref": "#/definitions/durationInMonths",
"title": "Please specify how many months you expect your project to last (from 2-12 months)",
"description": "Minimum 2 months - Maximum 12 months.
The scope of your funding request and this project is expected to produce the deliverables you specify in the proposal within 2-12 months.
If you believe your project will take longer than 12 months, consider reducing the project’s scope so that it becomes achievable within 12 months.
If your project completes earlier than scheduled so long as you have submitted your PoAs and Project Close-out report and video then your project can be closed out.
",
"minimum": 2,
- "maximum": 12,
- "format": "datetime:months"
+ "maximum": 12
},
"translated": {
- "type": "boolean",
+ "$ref": "#/definitions/yesNoChoice",
"title": "Please indicate if your proposal has been auto-translated into English from another language",
- "description": "YES/NO - Tick YES so readers are reminded that your proposal has been translated, and that they should be tolerant of any language imperfections.
You can either link a document with your proposal in its original language OR provide your response in your native language after the English language in each question if you wish.
Tick NO if your proposal has not been auto-translated into English from another language.
",
- "format": "yes/no"
+ "description": "YES/NO - Tick YES so readers are reminded that your proposal has been translated, and that they should be tolerant of any language imperfections.
You can either link a document with your proposal in its original language OR provide your response in your native language after the English language in each question if you wish.
Tick NO if your proposal has not been auto-translated into English from another language.
"
},
"problem": {
- "type": "string",
+ "$ref": "#/definitions/multiLineTextEntry",
"title": "What is the problem you want to solve? (200-character limit including spaces)",
"description": "Ensure you present a well-defined problem. What is the core issue that you hope to fix? Remember: the reader might not recognize the problem unless you state it clearly.
This answer will be displayed on the Catalyst voting app, so voters will see it even if they don't open your proposal to read it in detail.
",
- "contentMediaType": "text/plain",
- "pattern": "^[\\S\\s]$",
"maxLength": 200,
"minLength": 1
},
"solution": {
- "type": "string",
+ "$ref": "#/definitions/multiLineTextEntry",
"title": "Summarize your solution to the problem (200-character limit including spaces)",
"description": "Focus on what you are going to do, or make, or change, to solve the problem. So not 'There should be a way to....' but 'We will make a...'
Clearly state how the solution addresses the specific problem you have identified - connect the 'why' and the 'how'.
This answer will be displayed on the Catalyst voting app, so voters will see it even if they do not open your proposal and read it in detail.
",
- "contentMediaType": "text/plain",
- "pattern": "^[\\S\\s]$",
"maxLength": 200,
"minLength": 1
},
"links": {
- "type": "array",
+ "$ref": "#/definitions/uriList",
"title": "Website / GitHub repository, White paper, Marketing or any other relevant link",
"description": "Here, provide links to yours or your partner organization’s website, repository, or marketing. Alternatively, provide links to any whitepaper or other publication relevant to your proposal.
Note however that this is extra information that voters and Community Reviewers might choose not to read. You should not fail to include any of the questions in this form because you feel the answers can be found elsewhere.
If any links are specified make sure these are added in good order (first link must be present before specifying second). Also ensure all links include ‘https’. Without these steps, the form will not be submittable and show errors.
",
- "items": {
- "type": "string",
- "format": "uri",
- "contentMediaType": "text/plain",
- "maxLength": 1024
- },
- "uniqueItems": true,
- "default": [],
"minItems": 0,
"maxItems": 3
},
"dependencies": {
- "type": "string",
+ "$ref": "#/definitions/multiLineTextEntry",
"title": "If you have any dependencies then, please describe what the dependency is and why you believe it is essential for your project’s delivery. If NO, please write “No dependencies.”",
"description": "Here you should list any dependencies and prerequisites for your project’s success. These are usually external factors (such as third-party suppliers, external resources, third-party software, etc.) that may cause a delay, since a project has less control over them. In case of third party software, indicate whether you have the necessary licenses and permission to use such software.
",
- "contentMediaType": "text/plain",
- "pattern": "^[\\S\\s]$",
"maxLength": 1024,
"minLength": 0
},
"open_source": {
- "type": "boolean",
+ "$ref": "#/definitions/yesNoChoice",
"title": "Will your project’s output/s be fully open source?",
- "description": "Open source refers to something people can modify and share because its design is publicly accessible.
Open source software is software with source code that anyone can inspect, modify, and enhance. Conversely, only the original authors of proprietary software can legally copy, inspect, and alter that software.
",
- "format": "yes/no"
+ "description": "Open source refers to something people can modify and share because its design is publicly accessible.
Open source software is software with source code that anyone can inspect, modify, and enhance. Conversely, only the original authors of proprietary software can legally copy, inspect, and alter that software.
"
},
"license_info": {
- "type": "string",
+ "$ref": "#/definitions/multiLineTextEntry",
"title": "[GENERAL] Please provide here more information on the open source status of your project outputs",
"description": "If you answered YES to the above question:
If declaring the project is open source in the application form, the project should be open source-available throughout the entire lifecycle of the project with a declared open-source repository.
Please indicate here the type of license you intend to use for open source and provide any further information you feel is relevant to the open source status of your project outputs.
If only certain elements of your code will be open source please clarify which elements will be open source here.
If you answered NO to the above question, please give further details as to why your projects outputs will not be open source.
",
- "contentMediaType": "text/plain",
- "pattern": "^[\\S\\s]$",
"maxLength": 1024,
"minLength": 0
}
@@ -237,19 +246,26 @@
"type": "object",
"properties": {
"fund_rules": {
- "type": "string",
+ "$ref": "#/definitions/agreementConfirmation",
"title": "Fund Rules:",
- "description": "By submitting a proposal to Project Catalyst Fund13, I confirm that I have read and agree to be bound by the Fund Rules.
",
- "contentMediaType": "text/plain",
- "enum": [
- "Yes",
- "No"
- ],
- "default": "No",
- "pattern": "Yes",
- "format": "checkbox"
+ "description": "By submitting a proposal to Project Catalyst Fund13, I confirm that I have read and agree to be bound by the Fund Rules.
"
+ },
+ "terms_and_conditions": {
+ "$ref": "#/definitions/agreementConfirmation",
+ "title": "Terms and Conditions:",
+ "description": "By submitting a proposal to Project Catalyst Fund13, I confirm that I have read and agree to be bound by the Project Catalyst Terms and Conditions.
"
+ },
+ "privacy_policy": {
+ "$ref": "#/definitions/agreementConfirmation",
+ "title": "Privacy Policy: ",
+ "description": "I acknowledge and agree that any data I share in connection with my participation in Project Catalyst Fund13 will be collected, stored, used and processed in accordance with the Catalyst FC’s Privacy Policy.
"
}
- }
+ },
+ "required": [
+ "fund_rules",
+ "terms_and_conditions",
+ "privacy_policy"
+ ]
}
}
}
\ No newline at end of file
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/proposal.F14.example.json b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/proposal.F14.example.json
index d77c676cb9e..13813ee0f09 100644
--- a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/proposal.F14.example.json
+++ b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/proposal.F14.example.json
@@ -1,7 +1,7 @@
{
"$schema": "./0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json",
"general": {
- "title": "Single line plain text ..............................",
+ "title": "Single line plain text .....",
"links": [
"http://notauri",
"ftp://some_old_site",
@@ -14,6 +14,8 @@
"tag": "Learn to Earn"
},
"agreements": {
- "fund_rules": "Yes"
+ "fund_rules": true,
+ "terms_and_conditions": true,
+ "privacy_policy": true
}
}
\ No newline at end of file
From e89574f21f2e0f13bb2839fa6d788a7036930da8 Mon Sep 17 00:00:00 2001
From: Steven Johnson
Date: Thu, 5 Dec 2024 13:22:57 +0700
Subject: [PATCH 08/25] docs(cat-gateway): Suggested restructuring
---
.config/dictionaries/project.dic | 1 +
...8-9258-4fbc-a62e-7faa6e58318f.schema.json} | 577 +++++++++++++-----
.../F14-Generic/example.proposal.json | 2 +-
.../proposalTemplate.F14.example.json | 0
4 files changed, 436 insertions(+), 144 deletions(-)
rename docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/{proposalTemplate.F14.schema.json => 0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json} (80%)
delete mode 100644 docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/proposalTemplate.F14.example.json
diff --git a/.config/dictionaries/project.dic b/.config/dictionaries/project.dic
index 4b146db4d44..517820b0998 100644
--- a/.config/dictionaries/project.dic
+++ b/.config/dictionaries/project.dic
@@ -56,6 +56,7 @@ codepoints
collabs
commitlog
concatcp
+coproposers
coti
coverallsapp
CQLSH
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/proposalTemplate.F14.schema.json b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
similarity index 80%
rename from docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/proposalTemplate.F14.schema.json
rename to docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
index 2f75889e10a..b55c82a2a36 100644
--- a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/proposalTemplate.F14.schema.json
+++ b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
@@ -1,184 +1,266 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://cardano.org/schemas/catalyst/f14/proposal",
- "version": "1.0.0",
"title": "F14 Submission Form",
"description": "Schema for the F14 Catalyst Proposal Submission Form",
- "type": "object",
- "properties": {
- "$schema": {
+ "definitions": {
+ "schemaReferenceNonUI": {
+ "$comment": "NOT UI: used to identify the kind of template document used.",
"type": "string",
"format": "path",
- "const": "./proposalTemplate.F14.schema.json",
"readOnly": true
},
- "setup": {
+ "section": {
+ "$comment": "UI - Logical Document Section Break.",
+ "type": "object",
+ "additionalProperties": false
+ },
+ "subsection": {
+ "$comment": "UI - Logical Document Sub-Section Break.",
"type": "object",
+ "additionalProperties": false
+ },
+ "singleLineTextEntry": {
+ "$comment": "UI - Single Line text entry without any markup or rich text capability.",
+ "type": "string",
+ "contentMediaType": "text/plain",
+ "pattern": "^.*$"
+ },
+ "multiLineTextEntry": {
+ "$comment": "UI - Multiline text entry without any markup or rich text capability.",
+ "type": "string",
+ "contentMediaType": "text/plain",
+ "pattern": "^[\\S\\s]$"
+ },
+ "dropDownSingleSelect": {
+ "$comment": "UI - Drop Down Selection of a single entry from the defined enum.",
+ "type": "string",
+ "contentMediaType": "text/plain",
+ "pattern": "^.*$",
+ "format": "dropDownSingleSelect"
+ },
+ "multiSelect": {
+ "$comment": "UI - Multiselect from the given items.",
+ "type": "array",
+ "uniqueItems": true,
+ "format": "multiSelect"
+ },
+ "singleLineTextEntryList": {
+ "$comment": "UI - A Growable List of single line text (no markup or richtext).",
+ "type": "array",
+ "format": "singleLineTextEntryList",
+ "uniqueItems": true,
+ "default": [],
+ "items": {
+ "$ref": "#/definitions/singleLineTextEntry",
+ "maxLength": 1024
+ }
+ },
+ "tokenValueCardanoADA": {
+ "$comment": "UI - A Token Value denominated in Cardano ADA.",
+ "type": "integer",
+ "format": "token:cardano:ada"
+ },
+ "durationInMonths": {
+ "$comment": "UI - A Duration represented in total months.",
+ "type": "integer",
+ "format": "datetime:duration:months"
+ },
+ "yesNoChoice": {
+ "$comment": "UI - A Boolean choice, represented as a Yes/No selection. Yes = true.",
+ "type": "boolean",
+ "format": "yes/no",
+ "default": false
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "$schema": {
+ "$ref": "#/definitions/schemaReferenceNonUI",
+ "default": "./0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json",
+ "const": "./0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json"
+ },
+ "setup": {
+ "$ref": "#/definitions/section",
"title": "proposal setup",
"description": "Proposal title",
"properties": {
"title": {
- "type": "object",
+ "$ref": "#/definitions/subsection",
"title": "proposal setup",
"description": "Proposal title",
"properties": {
"title": {
- "type": "string",
+ "$ref": "#/definitions/singleLineTextEntry",
"title": "Proposal Title",
"description": "A clear, unambiguous, and concise title for your proposal",
"minLength": 1,
"maxLength": 60,
- "examples": ["DeFi Integration Platform for Cardano"],
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
+ "examples": [
+ "DeFi Integration Platform for Cardano"
+ ]
}
},
- "additionalProperties": false,
"required": [
"title"
]
},
"proposer": {
- "type": "object",
+ "$ref": "#/definitions/subsection",
"properties": {
- "mainApplicant": {
- "type": "string",
+ "applicant": {
+ "$ref": "#/definitions/singleLineTextEntry",
"title": "Name and surname of main applicant",
"description": "Name and surname of main applicant",
- "$comment": "Please provide the name and surname of the main applicant. The main applicant is considered as the individual responsible for the project and the person authorized to act on behalf of other applicants (where applicable).",
+ "x-guidance": "Please provide the name and surname of the main applicant. The main applicant is considered as the individual responsible for the project and the person authorized to act on behalf of other applicants (where applicable).",
"minLength": 2,
- "maxLength": 100,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
+ "maxLength": 100
},
- "applicantType": {
- "type": "string",
+ "type": {
+ "$ref": "#/definitions/dropDownSingleSelect",
"title": "Are you delivering this project as an individual or as an entity (whether formally incorporated or not)",
"description": "Are you delivering this project as an individual or as an entity (whether formally incorporated or not)",
- "$comment": "Please select from one of the following: 1. Individual 2. Entity (Incorporated) 3. Entity (Not Incorporated)",
+ "x-guidance": "Please select from one of the following: 1. Individual 2. Entity (Incorporated) 3. Entity (Not Incorporated)",
"enum": [
"Individual",
"Entity (Incorporated)",
"Entity (Not Incorporated)"
- ]
+ ],
+ "default": "Individual"
},
- "coProposers": {
- "type": "array",
+ "coproposers": {
+ "$ref": "#/definitions/singleLineTextEntryList",
"title": "Co-proposers and additional applicants",
"description": "Co-proposers and additional applicants",
- "$comment": "List any persons who are submitting the proposal jointly with the main applicant. Make sure you have confirmed approval/awareness with these individuals/accounts before adding them. If there is more than one proposer, identify the lead person who is authorized to act on behalf of other co-proposers. IMPORTANT A maximum of 6 (six) proposals can be led or co-proposed by the same applicant or enterprise. Please, reference Fund 13 rules for added detail.",
- "items": {
- "type": "string"
- },
- "maxItems": 5
+ "x-guidance": "List any persons who are submitting the proposal jointly with the main applicant. Make sure you have confirmed approval/awareness with these individuals/accounts before adding them. If there is more than one proposer, identify the lead person who is authorized to act on behalf of other co-proposers. IMPORTANT A maximum of 6 (six) proposals can be led or co-proposed by the same applicant or enterprise. Please, reference Fund 13 rules for added detail.",
+ "maxItems": 5,
+ "minItems": 0
}
},
- "required": ["mainApplicant", "applicantType"]
+ "required": [
+ "applicant",
+ "type"
+ ]
}
},
- "required": ["title", "proposer"]
+ "required": [
+ "title",
+ "proposer"
+ ]
},
- "proposalSummary": {
- "type": "object",
+ "summary": {
+ "$ref": "#/definitions/section",
"title": "Proposal Summary",
"description": "Key information about your proposal",
"properties": {
"budget": {
- "type": "object",
+ "$ref": "#/definitions/subsection",
"title": "Budget Information",
"properties": {
"requestedFunds": {
- "type": "number",
+ "$ref": "#/definitions/tokenValueCardanoADA",
"title": "Requested funds in ADA",
"description": "The amount of funding requested for your proposal",
+ "x-guidance": "There is a minimum and a maximum amount of funding that can be requested in a single Catalyst proposal. These are outlined below per each category: Minimum Funding Amount per proposal: Cardano Open: A15,000 Cardano Uses Cases: A15,000 Cardano Partners: A500,000 Maximum Funding Amount per proposal: Cardano Open: Developers (technical): A200,000 • Ecosystem (non-technical): A100,000 Cardano Uses Cases: Concept A150,000 Product: A500,000 Cardano Partners: Enterprise R&D A2,000,000 Growth & Acceleration: A2,000,000",
"minimum": 15000,
- "maximum": 2000000,
- "examples": ["There is a minimum and a maximum amount of funding that can be requested in a single Catalyst proposal. These are outlined below per each category: Minimum Funding Amount per proposal: Cardano Open: A15,000 Cardano Uses Cases: A15,000 Cardano Partners: A500,000 Maximum Funding Amount per proposal: Cardano Open: Developers (technical): A200,000 • Ecosystem (non-technical): A100,000 Cardano Uses Cases: Concept A150,000 Product: A500,000 Cardano Partners: Enterprise R&D A2,000,000 Growth & Acceleration: A2,000,000"],
- "format": "cardano:ada",
- "errorMessage": {
- "minimum": "Minimum funding amount is 15,000 ADA",
- "maximum": "Maximum funding amount is 2,000,000 ADA"
- }
+ "maximum": 2000000
}
- }
+ },
+ "required": [
+ "requestedFunds"
+ ]
},
"time": {
- "type": "object",
+ "$ref": "#/definitions/subsection",
"properties": {
- "projectDuration": {
- "type": "integer",
+ "duration": {
+ "$ref": "#/definitions.durationInMonths",
"title": "Project Duration in Months",
"description": "Specify the expected duration of your project. Projects must be completable within 2-12 months.",
+ "x-guidance": "Minimum 2 months-Maximum 12 months. The scope of your funding request and this project is expected to produce the deliverables you specify in the proposal within 2-12 months If you believe your project will take longer than 12 months, consider reducing the project's scope so that it becomes achievable within 12 months If your project completes earlier than scheduled so long as you have submitted your PoAs and Project Close-out report and video then your project can be closed out.",
"minimum": 2,
- "maximum": 12,
- "examples": ["Minimum 2 months-Maximum 12 months. The scope of your funding request and this project is expected to produce the deliverables you specify in the proposal within 2-12 months If you believe your project will take longer than 12 months, consider reducing the project's scope so that it becomes achievable within 12 months If your project completes earlier than scheduled so long as you have submitted your PoAs and Project Close-out report and video then your project can be closed out."]
+ "maximum": 12
}
},
- "required": ["projectDuration"]
+ "required": [
+ "projectDuration"
+ ]
},
"translation": {
- "type": "object",
+ "$ref": "#/definitions/subsection",
"title": "Translation Information",
"description": "Information about the proposal's language and translation status",
"properties": {
- "isTranslated": {
- "type": "boolean",
+ "translated": {
+ "$ref": "#/definitions/yesNoChoice",
"title": "Auto-translated Status",
- "description": "Indicate if your proposal has been auto-translated into English from another language",
- "default": false
+ "description": "Indicate if your proposal has been auto-translated into English from another language"
},
- "originalLanguage": {
- "type": "string",
+ "original": {
+ "$ref": "#/definitions/singleLineTextEntry",
"title": "Original Language",
"description": "If auto-translated, specify the original language of your proposal",
"minLength": 2,
"maxLength": 50,
- "examples": ["Spanish", "Japanese", "French"],
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
+ "examples": [
+ "Spanish",
+ "Japanese",
+ "French"
+ ]
},
- "translationNotes": {
- "type": "string",
+ "notes": {
+ "$ref": "#/definitions/multiLineTextEntry",
"title": "Translation Notes",
"description": "Additional notes about the translation or original language content",
- "maxLength": 500,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
+ "maxLength": 500
}
},
- "required": ["isTranslated"],
+ "required": [
+ "isTranslated"
+ ],
"dependencies": {
- "originalLanguage": ["isTranslated"],
- "translationNotes": ["isTranslated"]
+ "originalLanguage": [
+ "isTranslated"
+ ],
+ "translationNotes": [
+ "isTranslated"
+ ]
},
"if": {
- "properties": { "isTranslated": { "const": true } }
+ "properties": {
+ "isTranslated": {
+ "const": true
+ }
+ }
},
"then": {
- "required": ["originalLanguage"]
+ "required": [
+ "originalLanguage"
+ ]
}
},
"problem": {
- "type": "object",
+ "$ref": "#/definitions/subsection",
"title": "Problem Statement",
"description": "Define the problem your proposal aims to solve",
"properties": {
"statement": {
- "type": "string",
+ "$ref": "#/definitions/multiLineTextEntry",
"title": "Problem Description",
"description": "Clearly define the problem you aim to solve. This will be visible in the Catalyst voting app.",
"minLength": 10,
"maxLength": 200,
- "examples": ["The Cardano ecosystem lacks standardized tools for cross-protocol communication, resulting in fragmented user experiences and inefficient resource utilization."],
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
+ "examples": [
+ "The Cardano ecosystem lacks standardized tools for cross-protocol communication, resulting in fragmented user experiences and inefficient resource utilization."
+ ]
},
- "impactArea": {
- "type": "array",
+ "impact": {
+ "$ref": "#/definitions/multiSelect",
"title": "Impact Areas",
"description": "Select the areas that will be most impacted by solving this problem",
"items": {
- "type": "string",
+ "$ref": "singleLineTextEntry",
"enum": [
"Technical Infrastructure",
"User Experience",
@@ -193,26 +275,28 @@
]
},
"minItems": 1,
- "maxItems": 3,
- "uniqueItems": true
+ "maxItems": 3
}
},
- "required": ["statement", "impactArea"]
+ "required": [
+ "statement",
+ "impact"
+ ]
},
"solution": {
- "type": "object",
+ "$ref": "#/definitions/subsection",
"title": "Solution Overview",
"description": "Describe your proposed solution to the problem",
"properties": {
"summary": {
- "type": "string",
+ "$ref": "#/definitions/multiLineTextEntry",
"title": "Solution Summary",
"description": "Briefly describe your solution. Focus on what you will do or create to solve the problem.",
"minLength": 10,
"maxLength": 200,
- "examples": ["Develop an open-source integration framework that standardizes protocol communication and provides a unified API layer for seamless DeFi interactions."],
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
+ "examples": [
+ "Develop an open-source integration framework that standardizes protocol communication and provides a unified API layer for seamless DeFi interactions."
+ ]
},
"approach": {
"type": "string",
@@ -237,7 +321,10 @@
"uniqueItems": true
}
},
- "required": ["summary", "approach"]
+ "required": [
+ "summary",
+ "approach"
+ ]
},
"SupportingLinks": {
"type": "object",
@@ -294,7 +381,11 @@
"contentMediaType": "text/plain"
}
},
- "required": ["url", "type", "description"]
+ "required": [
+ "url",
+ "type",
+ "description"
+ ]
},
"minItems": 0,
"maxItems": 10,
@@ -375,26 +466,39 @@
"contentMediaType": "text/plain"
}
},
- "required": ["name", "type", "description"]
+ "required": [
+ "name",
+ "type",
+ "description"
+ ]
},
"minItems": 0,
"maxItems": 10
}
},
- "required": ["hasDependencies"],
+ "required": [
+ "hasDependencies"
+ ],
"dependencies": {
- "details": ["hasDependencies"]
+ "details": [
+ "hasDependencies"
+ ]
},
"if": {
- "properties": { "hasDependencies": { "const": true } }
+ "properties": {
+ "hasDependencies": {
+ "const": true
+ }
+ }
},
"then": {
- "required": ["details"]
+ "required": [
+ "details"
+ ]
}
}
}
},
-
"horizons": {
"type": "object",
"title": "Project Horizons",
@@ -564,16 +668,29 @@
"contentMediaType": "text/plain"
}
},
- "required": ["metric", "target", "measurement"]
+ "required": [
+ "metric",
+ "target",
+ "measurement"
+ ]
},
"minItems": 1,
"maxItems": 5
}
},
- "required": ["timeframe", "scale", "metrics"]
+ "required": [
+ "timeframe",
+ "scale",
+ "metrics"
+ ]
}
},
- "required": ["primaryCategory", "subCategory", "tags", "impact"]
+ "required": [
+ "primaryCategory",
+ "subCategory",
+ "tags",
+ "impact"
+ ]
},
"proposalDetails": {
"type": "object",
@@ -631,7 +748,12 @@
"contentMediaType": "text/plain"
}
},
- "required": ["description", "uniqueValue", "targetAudience", "implementation"]
+ "required": [
+ "description",
+ "uniqueValue",
+ "targetAudience",
+ "implementation"
+ ]
},
"impact": {
"type": "object",
@@ -687,7 +809,12 @@
"contentMediaType": "text/plain"
}
},
- "required": ["name", "description", "target", "measurement"]
+ "required": [
+ "name",
+ "description",
+ "target",
+ "measurement"
+ ]
},
"minItems": 2,
"maxItems": 5
@@ -708,7 +835,11 @@
"uniqueItems": true
}
},
- "required": ["communityBenefit", "metrics", "outputs"]
+ "required": [
+ "communityBenefit",
+ "metrics",
+ "outputs"
+ ]
},
"capability": {
"type": "object",
@@ -750,7 +881,11 @@
},
"impact": {
"type": "string",
- "enum": ["Low", "Medium", "High"],
+ "enum": [
+ "Low",
+ "Medium",
+ "High"
+ ],
"title": "Risk Impact"
},
"mitigation": {
@@ -762,7 +897,11 @@
"contentMediaType": "text/plain"
}
},
- "required": ["risk", "impact", "mitigation"]
+ "required": [
+ "risk",
+ "impact",
+ "mitigation"
+ ]
},
"minItems": 1,
"maxItems": 5
@@ -777,10 +916,19 @@
"contentMediaType": "text/plain"
}
},
- "required": ["teamExperience", "feasibilityApproach", "riskMitigation", "fundManagement"]
+ "required": [
+ "teamExperience",
+ "feasibilityApproach",
+ "riskMitigation",
+ "fundManagement"
+ ]
}
},
- "required": ["solution", "impact", "capability"]
+ "required": [
+ "solution",
+ "impact",
+ "capability"
+ ]
},
"milestones": {
"type": "object",
@@ -807,7 +955,10 @@
"maximum": 10
}
},
- "required": ["grantAmount", "numberOfMilestones"]
+ "required": [
+ "grantAmount",
+ "numberOfMilestones"
+ ]
},
"milestonesList": {
"type": "array",
@@ -870,7 +1021,11 @@
]
}
},
- "required": ["name", "description", "type"]
+ "required": [
+ "name",
+ "description",
+ "type"
+ ]
},
"minItems": 1,
"maxItems": 5
@@ -918,7 +1073,10 @@
"contentMediaType": "text/plain"
}
},
- "required": ["type", "description"]
+ "required": [
+ "type",
+ "description"
+ ]
},
"minItems": 1,
"maxItems": 3
@@ -944,7 +1102,11 @@
"maximum": 52
}
},
- "required": ["startDate", "endDate", "durationInWeeks"]
+ "required": [
+ "startDate",
+ "endDate",
+ "durationInWeeks"
+ ]
},
"budget": {
"type": "object",
@@ -983,12 +1145,19 @@
"contentMediaType": "text/plain"
}
},
- "required": ["category", "amount", "description"]
+ "required": [
+ "category",
+ "amount",
+ "description"
+ ]
},
"minItems": 1
}
},
- "required": ["amount", "breakdown"]
+ "required": [
+ "amount",
+ "breakdown"
+ ]
}
},
"required": [
@@ -1058,7 +1227,12 @@
"contentMediaType": "text/plain"
}
},
- "required": ["summary", "keyAchievements", "lessonsLearned", "futureSteps"]
+ "required": [
+ "summary",
+ "keyAchievements",
+ "lessonsLearned",
+ "futureSteps"
+ ]
},
"demoVideo": {
"type": "object",
@@ -1087,13 +1261,24 @@
"contentMediaType": "text/plain"
}
},
- "required": ["url", "duration", "description"]
+ "required": [
+ "url",
+ "duration",
+ "description"
+ ]
}
},
- "required": ["closeoutReport", "demoVideo"]
+ "required": [
+ "closeoutReport",
+ "demoVideo"
+ ]
}
},
- "required": ["milestonesConfig", "milestonesList", "finalMilestone"]
+ "required": [
+ "milestonesConfig",
+ "milestonesList",
+ "finalMilestone"
+ ]
},
"finalPitch": {
"type": "object",
@@ -1185,12 +1370,20 @@
"contentMediaType": "text/plain"
}
},
- "required": ["type", "url"]
+ "required": [
+ "type",
+ "url"
+ ]
},
"maxItems": 5
}
},
- "required": ["name", "role", "expertise", "experience"]
+ "required": [
+ "name",
+ "role",
+ "expertise",
+ "experience"
+ ]
},
"minItems": 1,
"maxItems": 10
@@ -1244,12 +1437,19 @@
"contentMediaType": "text/uri-list"
}
},
- "required": ["projectName", "description", "relevance"]
+ "required": [
+ "projectName",
+ "description",
+ "relevance"
+ ]
},
"maxItems": 5
}
},
- "required": ["members", "teamCapabilities"]
+ "required": [
+ "members",
+ "teamCapabilities"
+ ]
},
"budget": {
"type": "object",
@@ -1318,12 +1518,21 @@
"contentMediaType": "text/plain"
}
},
- "required": ["item", "cost", "justification"]
+ "required": [
+ "item",
+ "cost",
+ "justification"
+ ]
},
"minItems": 1
}
},
- "required": ["category", "amount", "description", "breakdown"]
+ "required": [
+ "category",
+ "amount",
+ "description",
+ "breakdown"
+ ]
},
"minItems": 1
},
@@ -1353,15 +1562,25 @@
"maximum": 100
}
},
- "required": ["milestone", "amount", "percentage"]
+ "required": [
+ "milestone",
+ "amount",
+ "percentage"
+ ]
},
"minItems": 1
}
},
- "required": ["distributionSchedule"]
+ "required": [
+ "distributionSchedule"
+ ]
}
},
- "required": ["totalBudget", "categories", "timeline"]
+ "required": [
+ "totalBudget",
+ "categories",
+ "timeline"
+ ]
},
"valueProposition": {
"type": "object",
@@ -1409,7 +1628,11 @@
"contentMediaType": "text/plain"
}
},
- "required": ["metric", "target", "justification"]
+ "required": [
+ "metric",
+ "target",
+ "justification"
+ ]
},
"minItems": 2,
"maxItems": 5
@@ -1438,10 +1661,19 @@
"maxItems": 5
}
},
- "required": ["costBenefitAnalysis", "impactMetrics", "longTermValue", "communityBenefits"]
+ "required": [
+ "costBenefitAnalysis",
+ "impactMetrics",
+ "longTermValue",
+ "communityBenefits"
+ ]
}
},
- "required": ["team", "budget", "valueProposition"]
+ "required": [
+ "team",
+ "budget",
+ "valueProposition"
+ ]
},
"mandatoryAcknowledgments": {
"type": "object",
@@ -1463,7 +1695,10 @@
"title": "Fund Rules Version",
"description": "Version of the Fund Rules being acknowledged",
"pattern": "^F[0-9]{1,3}$",
- "examples": ["F14", "F15"]
+ "examples": [
+ "F14",
+ "F15"
+ ]
},
"timestamp": {
"type": "string",
@@ -1471,10 +1706,16 @@
"description": "When the rules were acknowledged",
"format": "date-time",
"pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]+)?(Z|[+-][0-9]{2}:[0-9]{2})$",
- "examples": ["2024-01-20T15:30:00Z"]
+ "examples": [
+ "2024-01-20T15:30:00Z"
+ ]
}
},
- "required": ["acknowledgment", "version", "timestamp"]
+ "required": [
+ "acknowledgment",
+ "version",
+ "timestamp"
+ ]
},
"termsAndConditions": {
"type": "object",
@@ -1491,7 +1732,10 @@
"title": "Terms Version",
"description": "Version of the Terms and Conditions being acknowledged",
"pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$",
- "examples": ["1.0.0", "2.1.3"]
+ "examples": [
+ "1.0.0",
+ "2.1.3"
+ ]
},
"documentUrl": {
"type": "string",
@@ -1507,10 +1751,17 @@
"description": "When the terms were acknowledged",
"format": "date-time",
"pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]+)?(Z|[+-][0-9]{2}:[0-9]{2})$",
- "examples": ["2024-01-20T15:30:00Z"]
+ "examples": [
+ "2024-01-20T15:30:00Z"
+ ]
}
},
- "required": ["acknowledgment", "version", "timestamp", "documentUrl"]
+ "required": [
+ "acknowledgment",
+ "version",
+ "timestamp",
+ "documentUrl"
+ ]
},
"privacyPolicy": {
"type": "object",
@@ -1527,7 +1778,10 @@
"title": "Privacy Policy Version",
"description": "Version of the Privacy Policy being acknowledged",
"pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$",
- "examples": ["1.0.0", "2.1.3"]
+ "examples": [
+ "1.0.0",
+ "2.1.3"
+ ]
},
"documentUrl": {
"type": "string",
@@ -1543,10 +1797,17 @@
"description": "When the privacy policy was acknowledged",
"format": "date-time",
"pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]+)?(Z|[+-][0-9]{2}:[0-9]{2})$",
- "examples": ["2024-01-20T15:30:00Z"]
+ "examples": [
+ "2024-01-20T15:30:00Z"
+ ]
}
},
- "required": ["acknowledgment", "version", "timestamp", "documentUrl"]
+ "required": [
+ "acknowledgment",
+ "version",
+ "timestamp",
+ "documentUrl"
+ ]
},
"intellectualProperty": {
"type": "object",
@@ -1575,7 +1836,13 @@
"properties": {
"documentType": {
"type": "string",
- "enum": ["patent", "trademark", "copyright", "license", "other"],
+ "enum": [
+ "patent",
+ "trademark",
+ "copyright",
+ "license",
+ "other"
+ ],
"description": "Type of IP documentation"
},
"documentUrl": {
@@ -1591,7 +1858,11 @@
"contentMediaType": "text/plain"
}
},
- "required": ["documentType", "documentUrl", "description"]
+ "required": [
+ "documentType",
+ "documentUrl",
+ "description"
+ ]
},
"maxItems": 10
},
@@ -1601,10 +1872,15 @@
"description": "When the IP declaration was made",
"format": "date-time",
"pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]+)?(Z|[+-][0-9]{2}:[0-9]{2})$",
- "examples": ["2024-01-20T15:30:00Z"]
+ "examples": [
+ "2024-01-20T15:30:00Z"
+ ]
}
},
- "required": ["acknowledgment", "timestamp"]
+ "required": [
+ "acknowledgment",
+ "timestamp"
+ ]
},
"compliance": {
"type": "object",
@@ -1646,10 +1922,18 @@
"description": "When the compliance declaration was made",
"format": "date-time",
"pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]+)?(Z|[+-][0-9]{2}:[0-9]{2})$",
- "examples": ["2024-01-20T15:30:00Z"]
+ "examples": [
+ "2024-01-20T15:30:00Z"
+ ]
}
},
- "required": ["legalCompliance", "noConflictOfInterest", "accurateInformation", "jurisdictions", "timestamp"]
+ "required": [
+ "legalCompliance",
+ "noConflictOfInterest",
+ "accurateInformation",
+ "jurisdictions",
+ "timestamp"
+ ]
},
"additionalAcknowledgments": {
"type": "array",
@@ -1692,10 +1976,17 @@
"title": "Acknowledgment Timestamp",
"format": "date-time",
"pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]+)?(Z|[+-][0-9]{2}:[0-9]{2})$",
- "examples": ["2024-01-20T15:30:00Z"]
+ "examples": [
+ "2024-01-20T15:30:00Z"
+ ]
}
},
- "required": ["type", "acknowledgment", "description", "timestamp"]
+ "required": [
+ "type",
+ "acknowledgment",
+ "description",
+ "timestamp"
+ ]
}
}
},
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/example.proposal.json b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/example.proposal.json
index 6c1318570dd..25a479f83b6 100644
--- a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/example.proposal.json
+++ b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/example.proposal.json
@@ -1,5 +1,5 @@
{
- "$schema": "./proposalTemplate.F14.schema.json",
+ "$schema": "./0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json",
"setup": {
"title": {
"title": "Cardano DeFi Integration Platform"
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/proposalTemplate.F14.example.json b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/proposalTemplate.F14.example.json
deleted file mode 100644
index e69de29bb2d..00000000000
From d4b99dea2ac9dc09b7cc65d12886c915101964cd Mon Sep 17 00:00:00 2001
From: Nathan Bogale
Date: Thu, 5 Dec 2024 16:59:52 +0300
Subject: [PATCH 09/25] fix: added all guidance as html, added additional sub
fields fields
---
...38-9258-4fbc-a62e-7faa6e58318f.schema.json | 408 +++---------------
.../proposal/F14-Generic/readModifications.md | 192 +++++++++
2 files changed, 261 insertions(+), 339 deletions(-)
create mode 100644 docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/readModifications.md
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
index b55c82a2a36..36ce520028e 100644
--- a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
+++ b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
@@ -94,11 +94,11 @@
"title": {
"$ref": "#/definitions/singleLineTextEntry",
"title": "Proposal Title",
- "description": "A clear, unambiguous, and concise title for your proposal",
+ "description": "Proposal title
Please note we suggest you use no more than 60 characters for your proposal title so that it can be easily viewed in the voting app.
",
"minLength": 1,
"maxLength": 60,
"examples": [
- "DeFi Integration Platform for Cardano"
+ "The title should clearly express what the proposal is about. Voters can see the title in the voting app, even without opening the proposal, so a clear, unambiguous, and concise title is very important.
"
]
}
},
@@ -113,7 +113,7 @@
"$ref": "#/definitions/singleLineTextEntry",
"title": "Name and surname of main applicant",
"description": "Name and surname of main applicant",
- "x-guidance": "Please provide the name and surname of the main applicant. The main applicant is considered as the individual responsible for the project and the person authorized to act on behalf of other applicants (where applicable).",
+ "x-guidance": "Please provide the name and surname of the main applicant. The main applicant is considered as the individual responsible for the project and the person authorized to act on behalf of other applicants (where applicable).
",
"minLength": 2,
"maxLength": 100
},
@@ -121,7 +121,7 @@
"$ref": "#/definitions/dropDownSingleSelect",
"title": "Are you delivering this project as an individual or as an entity (whether formally incorporated or not)",
"description": "Are you delivering this project as an individual or as an entity (whether formally incorporated or not)",
- "x-guidance": "Please select from one of the following: 1. Individual 2. Entity (Incorporated) 3. Entity (Not Incorporated)",
+ "x-guidance": "Please select from one of the following:
- Individual
- Entity (Incorporated)
- Entity (Not Incorporated)
",
"enum": [
"Individual",
"Entity (Incorporated)",
@@ -133,7 +133,7 @@
"$ref": "#/definitions/singleLineTextEntryList",
"title": "Co-proposers and additional applicants",
"description": "Co-proposers and additional applicants",
- "x-guidance": "List any persons who are submitting the proposal jointly with the main applicant. Make sure you have confirmed approval/awareness with these individuals/accounts before adding them. If there is more than one proposer, identify the lead person who is authorized to act on behalf of other co-proposers. IMPORTANT A maximum of 6 (six) proposals can be led or co-proposed by the same applicant or enterprise. Please, reference Fund 13 rules for added detail.",
+ "x-guidance": "List any persons who are submitting the proposal jointly with the main applicant. Make sure you have confirmed approval/awareness with these individuals/accounts before adding them. If there is more than one proposer, identify the lead person who is authorized to act on behalf of other co-proposers. IMPORTANT A maximum of 6 (six) proposals can be led or co-proposed by the same applicant or enterprise. Please, reference Fund 13 rules for added detail.
",
"maxItems": 5,
"minItems": 0
}
@@ -162,7 +162,7 @@
"$ref": "#/definitions/tokenValueCardanoADA",
"title": "Requested funds in ADA",
"description": "The amount of funding requested for your proposal",
- "x-guidance": "There is a minimum and a maximum amount of funding that can be requested in a single Catalyst proposal. These are outlined below per each category: Minimum Funding Amount per proposal: Cardano Open: A15,000 Cardano Uses Cases: A15,000 Cardano Partners: A500,000 Maximum Funding Amount per proposal: Cardano Open: Developers (technical): A200,000 • Ecosystem (non-technical): A100,000 Cardano Uses Cases: Concept A150,000 Product: A500,000 Cardano Partners: Enterprise R&D A2,000,000 Growth & Acceleration: A2,000,000",
+ "x-guidance": "There is a minimum and a maximum amount of funding that can be requested in a single Catalyst proposal. These are outlined below per each category:
Minimum Funding Amount per proposal:
Cardano Open: A15,000
Cardano Uses Cases: A15,000
Cardano Partners: A500,000
Maximum Funding Amount per proposal:
Cardano Open:
- Developers (technical): A200,000
- Ecosystem (non-technical): A100,000
Cardano Uses Cases:
- Concept A150,000
- Product: A500,000
Cardano Partners:
- Enterprise R&D A2,000,000
- Growth & Acceleration: A2,000,000
",
"minimum": 15000,
"maximum": 2000000
}
@@ -178,7 +178,7 @@
"$ref": "#/definitions.durationInMonths",
"title": "Project Duration in Months",
"description": "Specify the expected duration of your project. Projects must be completable within 2-12 months.",
- "x-guidance": "Minimum 2 months-Maximum 12 months. The scope of your funding request and this project is expected to produce the deliverables you specify in the proposal within 2-12 months If you believe your project will take longer than 12 months, consider reducing the project's scope so that it becomes achievable within 12 months If your project completes earlier than scheduled so long as you have submitted your PoAs and Project Close-out report and video then your project can be closed out.",
+ "x-guidance": "Minimum 2 months-Maximum 12 months. The scope of your funding request and this project is expected to produce the deliverables you specify in the proposal within 2-12 months If you believe your project will take longer than 12 months, consider reducing the project's scope so that it becomes achievable within 12 months If your project completes earlier than scheduled so long as you have submitted your PoAs and Project Close-out report and video then your project can be closed out.
",
"minimum": 2,
"maximum": 12
}
@@ -195,7 +195,8 @@
"translated": {
"$ref": "#/definitions/yesNoChoice",
"title": "Auto-translated Status",
- "description": "Indicate if your proposal has been auto-translated into English from another language"
+ "description": "Indicate if your proposal has been auto-translated into English from another language",
+ "x-guidance": "Tick YES if your proposal has been auto-translated into English from another language so readers are reminded that your proposal has been translated, and that they should be tolerant of any language imperfections. Tick NO if your proposal has not been auto-translated into English from another language
"
},
"original": {
"$ref": "#/definitions/singleLineTextEntry",
@@ -251,9 +252,7 @@
"description": "Clearly define the problem you aim to solve. This will be visible in the Catalyst voting app.",
"minLength": 10,
"maxLength": 200,
- "examples": [
- "The Cardano ecosystem lacks standardized tools for cross-protocol communication, resulting in fragmented user experiences and inefficient resource utilization."
- ]
+ "x-guidance": "Ensure you present a well-defined problem. What is the core issue that you hope to fix? Remember: the reader might not recognize the problem unless you state it clearly. This answer will be displayed on the Catalyst voting app, so voters will see it even if they don't open your proposal to read it in detail.
"
},
"impact": {
"$ref": "#/definitions/multiSelect",
@@ -294,9 +293,7 @@
"description": "Briefly describe your solution. Focus on what you will do or create to solve the problem.",
"minLength": 10,
"maxLength": 200,
- "examples": [
- "Develop an open-source integration framework that standardizes protocol communication and provides a unified API layer for seamless DeFi interactions."
- ]
+ "x-guidance":"Focus on what you are going to do, or make, or change, to solve the problem. So not 'There should be a way to....' but 'We will make a Clearly state how the solution addresses the specific problem you have identified - connect the 'why' and the 'how' This answer will be displayed on the Catalyst voting app, so voters will see it even if they do not open your proposal and read it in detail.
"
},
"approach": {
"type": "string",
@@ -335,6 +332,7 @@
"type": "array",
"title": "Resource Links",
"description": "Links to relevant documentation, code repositories, or marketing materials. All links must use HTTPS.",
+ "x-guidance": "Here, provide links to yours or your partner organization's website, repository, or marketing. Alternatively, provide links to any whitepaper or other publication relevant to your proposal. Note however that this is extra information that voters and Community Reviewers might choose not to read. You should not fail to include any of the questions in this form because you feel the answers can be found elsewhere. If any links are specified make sure these are added in good order (first link must be present before specifying second). Also ensure all links include https. Without these steps, the form will not be submittable and show errors
",
"items": {
"type": "object",
"properties": {
@@ -426,6 +424,7 @@
"type": "array",
"title": "Dependency Details",
"description": "List and describe each dependency",
+ "x-guidance": "Here you should list any dependencies and prerequisites for your project's success. These are usually external factors (such as third-party suppliers, external resources, third-party software, etc.) that may cause a delay, since a project has less control over them. In case of third party software, indicate whether you have the necessary licenses and permission to use such software.
",
"items": {
"type": "object",
"properties": {
@@ -496,6 +495,49 @@
"details"
]
}
+ },
+ "open_source": {
+ "title": "Project Open Source",
+ "description": "Will your project's output/be s fully open source? Open source refers to something people can modify and share because its design is publicly accessible.",
+ "x-guidance":"Open source software is software with source code that anyone can inspect, modify, and enhance. Conversely, only the original authors of proprietary software can legally copy, inspect, and alter that software
",
+ "properties": {
+ "open_source": {
+ "$ref": "#/definitions/yesNoChoice",
+ "title": "Is Project Open Source?",
+ "description": "Will your project's output/be s fully open source? Open source refers to something people can modify and share because its design is publicly accessible.",
+ "x-guidance": "Open source software is software with source code that anyone can inspect, modify, and enhance. Conversely, only the original authors of proprietary software can legally copy, inspect, and alter that software
"
+ },
+ "more_information": {
+ "$ref": "#/definitions/multiLineTextEntry",
+ "title": "More Information",
+ "description": "Please provide here more information on the open source status of your project outputs",
+ "maxLength": 500,
+ "x-guidance": "If you answered YES to the above question If declaring the project is open source in the application form, the project should be open source-available throughout the entire lifecycle of the project with a declared open-source repository. Please indicate here the type of license you intend to use for open source and provide any further information you feel is relevant to the open source status of your project outputs If only certain elements of your code will be open source please clarify which elements will be open source here. If you answered NO to the above question, please give further details as to why your projects outputs will not be open source METADATA
"
+ }
+ },
+ "required": [
+ "isOpenSource"
+ ],
+ "dependencies": {
+ "open_source": [
+ "isOpenSource"
+ ],
+ "more_information": [
+ "isOpenSource"
+ ]
+ },
+ "if": {
+ "properties": {
+ "isOpenSource": {
+ "const": true
+ }
+ }
+ },
+ "then": {
+ "required": [
+ "more_information"
+ ]
+ }
}
}
},
@@ -508,6 +550,7 @@
"type": "object",
"title": "Project Category",
"description": "Select the most relevant category and tags for your project",
+ "x-guidance": "Please choose the most relevant category group and tag related to the outcomes of your proposal. Can select only one group and one tag.
",
"properties": {
"primaryCategory": {
"type": "string",
@@ -701,6 +744,7 @@
"type": "object",
"title": "Solution Description",
"description": "Detailed description of your proposed solution",
+ "x-guidance": "YOUR PROJECT AND SOLUTION
How you write this section will depend on what type of proposal you are writing. You might want to include details on:
- How do you perceive the problem you are solving?
- What are your reasons for approaching it in the way that you have?
- Who will your project engage?
- How will you demonstrate or prove your impact?
Explain what is unique about your solution, who will benefit, and why this is important to Cardano.
",
"properties": {
"description": {
"type": "string",
@@ -759,6 +803,7 @@
"type": "object",
"title": "Project Impact",
"description": "Define and measure the impact of your project",
+ "x-guidance": "Please include here a description of how you intend to measure impact (whether quantitative or qualitative) and how and with whom you will share your outputs:
- In what way will the success of your project bring value to the Cardano Community?
- How will you measure this impact?
- How will you share the outputs and opportunities that result from your project?
",
"properties": {
"communityBenefit": {
"type": "string",
@@ -845,6 +890,7 @@
"type": "object",
"title": "Capability & Feasibility",
"description": "Demonstrate your ability to deliver the project successfully",
+ "x-guidance":"Please describe your existing capabilities that demonstrate how and why you believe you're best suited to deliver this project? Please include the steps or processes that demonstrate that you can be trusted to manage funds properly.
",
"properties": {
"teamExperience": {
"type": "string",
@@ -864,48 +910,6 @@
"pattern": "^[\\S\\s]*$",
"contentMediaType": "text/plain"
},
- "riskMitigation": {
- "type": "array",
- "title": "Risk Mitigation",
- "description": "Key risks and mitigation strategies",
- "items": {
- "type": "object",
- "properties": {
- "risk": {
- "type": "string",
- "title": "Risk Description",
- "minLength": 10,
- "maxLength": 200,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- },
- "impact": {
- "type": "string",
- "enum": [
- "Low",
- "Medium",
- "High"
- ],
- "title": "Risk Impact"
- },
- "mitigation": {
- "type": "string",
- "title": "Mitigation Strategy",
- "minLength": 20,
- "maxLength": 300,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- }
- },
- "required": [
- "risk",
- "impact",
- "mitigation"
- ]
- },
- "minItems": 1,
- "maxItems": 5
- },
"fundManagement": {
"type": "string",
"title": "Fund Management",
@@ -919,7 +923,6 @@
"required": [
"teamExperience",
"feasibilityApproach",
- "riskMitigation",
"fundManagement"
]
}
@@ -934,6 +937,7 @@
"type": "object",
"title": "Project Milestones",
"description": "Detailed project milestones and deliverables",
+ "x-guidance": "A clear set of milestones and acceptance criteria will demonstrate your capability to deliver the project as proposed. More guidance on submitting milestones as part of your project proposal can be found here
For Grant Amounts of up to 75k ada, at least 2 milestones, plus the final one including Project Close-out Report and Video, must be included (3 milestones in total)
For Grant Amounts over 75k ada up to 150k ada, at least 3 milestones, plus the final one including Project Close-out Report and Video, must be included (4 milestones in total)
For Grant Amounts over 150k ada up to 300k ada, at least 4 milestones, plus the final one including Project Close-out Report and Video, must be included (5 milestones in total)
For Grant Amounts exceeding 300k ada, at least 5 milestones, plus the final one including Project Close-out Report and Video, must be included (6 milestones in total)
",
"properties": {
"milestonesConfig": {
"type": "object",
@@ -951,8 +955,8 @@
"type": "integer",
"title": "Number of Milestones",
"description": "Total number of milestones including the final milestone",
- "minimum": 3,
- "maximum": 10
+ "minimum": 2,
+ "maximum": 6
}
},
"required": [
@@ -1172,112 +1176,11 @@
},
"minItems": 3,
"maxItems": 10
- },
- "finalMilestone": {
- "type": "object",
- "title": "Final Milestone",
- "description": "Project close-out milestone with final report and video",
- "properties": {
- "closeoutReport": {
- "type": "object",
- "title": "Project Close-out Report",
- "properties": {
- "summary": {
- "type": "string",
- "title": "Project Summary",
- "description": "Overall summary of project achievements",
- "minLength": 100,
- "maxLength": 2000,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- },
- "keyAchievements": {
- "type": "array",
- "title": "Key Achievements",
- "items": {
- "type": "string",
- "minLength": 10,
- "maxLength": 200,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- },
- "minItems": 1,
- "maxItems": 10
- },
- "lessonsLearned": {
- "type": "array",
- "title": "Lessons Learned",
- "items": {
- "type": "string",
- "minLength": 20,
- "maxLength": 500,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- },
- "minItems": 1,
- "maxItems": 5
- },
- "futureSteps": {
- "type": "string",
- "title": "Future Steps",
- "description": "Plans for project continuation or future development",
- "minLength": 50,
- "maxLength": 1000,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- }
- },
- "required": [
- "summary",
- "keyAchievements",
- "lessonsLearned",
- "futureSteps"
- ]
- },
- "demoVideo": {
- "type": "object",
- "title": "Project Demo Video",
- "properties": {
- "url": {
- "type": "string",
- "title": "Video URL",
- "format": "uri",
- "pattern": "^https://",
- "pattern": "^https?://[\\w\\-]+(\\.[\\w\\-]+)+[/#?]?.*$",
- "contentMediaType": "text/uri-list"
- },
- "duration": {
- "type": "integer",
- "title": "Duration in Minutes",
- "minimum": 3,
- "maximum": 15
- },
- "description": {
- "type": "string",
- "title": "Video Description",
- "minLength": 50,
- "maxLength": 500,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- }
- },
- "required": [
- "url",
- "duration",
- "description"
- ]
- }
- },
- "required": [
- "closeoutReport",
- "demoVideo"
- ]
- }
+ }
},
"required": [
"milestonesConfig",
- "milestonesList",
- "finalMilestone"
+ "milestonesList"
]
},
"finalPitch": {
@@ -1387,68 +1290,10 @@
},
"minItems": 1,
"maxItems": 10
- },
- "teamCapabilities": {
- "type": "string",
- "title": "Team Capabilities",
- "description": "Overview of the team's collective capabilities and why they are best suited for this project",
- "minLength": 100,
- "maxLength": 1000,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- },
- "previousWork": {
- "type": "array",
- "title": "Previous Work",
- "description": "Examples of relevant previous work or projects",
- "items": {
- "type": "object",
- "properties": {
- "projectName": {
- "type": "string",
- "title": "Project Name",
- "minLength": 3,
- "maxLength": 100,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- },
- "description": {
- "type": "string",
- "title": "Project Description",
- "minLength": 50,
- "maxLength": 500,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- },
- "relevance": {
- "type": "string",
- "title": "Relevance to Current Proposal",
- "minLength": 50,
- "maxLength": 300,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- },
- "url": {
- "type": "string",
- "title": "Project URL",
- "format": "uri",
- "pattern": "^https://",
- "pattern": "^https?://[\\w\\-]+(\\.[\\w\\-]+)+[/#?]?.*$",
- "contentMediaType": "text/uri-list"
- }
- },
- "required": [
- "projectName",
- "description",
- "relevance"
- ]
- },
- "maxItems": 5
}
},
"required": [
- "members",
- "teamCapabilities"
+ "members"
]
},
"budget": {
@@ -1493,94 +1338,21 @@
"maxLength": 300,
"pattern": "^[\\S\\s]*$",
"contentMediaType": "text/plain"
- },
- "breakdown": {
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "item": {
- "type": "string",
- "minLength": 5,
- "maxLength": 100,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- },
- "cost": {
- "type": "number",
- "minimum": 0
- },
- "justification": {
- "type": "string",
- "minLength": 20,
- "maxLength": 200,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- }
- },
- "required": [
- "item",
- "cost",
- "justification"
- ]
- },
- "minItems": 1
}
},
"required": [
"category",
"amount",
- "description",
- "breakdown"
+ "description"
]
},
"minItems": 1
- },
- "timeline": {
- "type": "object",
- "title": "Budget Timeline",
- "properties": {
- "distributionSchedule": {
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "milestone": {
- "type": "string",
- "minLength": 5,
- "maxLength": 100,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- },
- "amount": {
- "type": "number",
- "minimum": 0
- },
- "percentage": {
- "type": "number",
- "minimum": 0,
- "maximum": 100
- }
- },
- "required": [
- "milestone",
- "amount",
- "percentage"
- ]
- },
- "minItems": 1
- }
- },
- "required": [
- "distributionSchedule"
- ]
}
},
"required": [
"totalBudget",
- "categories",
- "timeline"
- ]
+ "categories"
+ ]
},
"valueProposition": {
"type": "object",
@@ -1596,47 +1368,6 @@
"pattern": "^[\\S\\s]*$",
"contentMediaType": "text/plain"
},
- "impactMetrics": {
- "type": "array",
- "title": "Impact Metrics",
- "description": "Specific metrics that demonstrate value for money",
- "items": {
- "type": "object",
- "properties": {
- "metric": {
- "type": "string",
- "title": "Metric Name",
- "minLength": 5,
- "maxLength": 100,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- },
- "target": {
- "type": "string",
- "title": "Target Value",
- "minLength": 1,
- "maxLength": 100,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- },
- "justification": {
- "type": "string",
- "title": "Value Justification",
- "minLength": 50,
- "maxLength": 300,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- }
- },
- "required": [
- "metric",
- "target",
- "justification"
- ]
- },
- "minItems": 2,
- "maxItems": 5
- },
"longTermValue": {
"type": "string",
"title": "Long-term Value",
@@ -1663,7 +1394,6 @@
},
"required": [
"costBenefitAnalysis",
- "impactMetrics",
"longTermValue",
"communityBenefits"
]
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/readModifications.md b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/readModifications.md
new file mode 100644
index 00000000000..8ca17618a52
--- /dev/null
+++ b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/readModifications.md
@@ -0,0 +1,192 @@
+# F14-Generic
+## Changes to the proposal template fields
+
+**Problem:**
+ - Statement
+ - Impact (select):
+ - "Technical Infrastructure",
+ - "User Experience",
+ - "Developer Tooling",
+ - "Community Growth",
+ - "Economic Sustainability",
+ - "Interoperability",
+ - "Security",
+ - "Scalability",
+ - "Education",
+ - "Adoption"
+
+
+
+**Solution:**
+ - summary
+ - approach
+ - innovative aspects
+
+**Supporting links:**
+ - Links
+ - Url
+ - Description
+ - Type (select):
+ - "GitHub Repository",
+ - "Documentation",
+ - "Whitepaper",
+ - "Website",
+ - "Marketing Material",
+ - "Technical Specification",
+ - "Research Paper",
+ - "Blog Post",
+ - "Social Media",
+ - "Other"
+ - Main Repository link
+ - Documentation link
+
+**Dependencies**
+ - detail:
+ - name
+ - description
+ - type:
+ - "Technical"
+ - "Organizational"
+ - "Legal"
+ - "Financial"
+ - "Other"
+ - mitigationPlan
+
+**Horizons:**
+ - tags:
+ - additional tags to be entered for the project -> on top of category and subcategory
+ + Impact:
+ + timeframe:
+ + "Short-term (0-6 months)"
+ + "Medium-term (6-18 months)"
+ + "Long-term (18+ months)"
+ + scale:
+ + "Local",
+ + "Regional",
+ + "Global"
+ + metrics:
+ + "metric name",
+ + "target",
+ + "measurement"
+
+- Product Details:
+ - Solution:
+ - description
+ + unique value proposition
+ + target audience
+ + implementation approach
+ - Impact:
+ + communityBenefit
+ + Metrics
+ + name
+ + description
+ + target
+ + measurement
+ + Project outputs
+ - Capability:
+ + Team Experience
+ + Feasibility Approach
+ + Fund Management: (How will you ensure proper management and accountability of funds?)
+
+
+**Milestones:**
+ + milestonesConfig:
+ + grantAmount
+ + numberOfMilestones
+ + milestonesList:
+ - milestone:
+ - title
+ + description
+ + deliverables
+ + name
+ + description
+ + type
+ + "Documentation"
+ + "Software"
+ + "Report"
+ + "Presentation"
+ + "Video"
+ + "Other"
+ + evidenceOfCompletion
+ + type
+ + "Code Repository"
+ + "Documentation"
+ + "Demo Video"
+ + "Test Results"
+ + "Metrics Report"
+ + "User Feedback"
+ + "Other"
+ + description
+ + timeline
+ + startDate
+ + endDate
+ + durationInWeeks
+ + budget
+ + amount
+ + breakdown
+ + category
+ + "Development"
+ + "Design"
+ + "Marketing"
+ + "Operations"
+ + "Other"
+ + amount
+ + description
+**Final Pitch**
+ + team
+ + members
+ + name
+ + role
+ + expertise
+ + experience
+ + links
+ + type
+ + url
+ + description
+ + budget
+ + total budget
+ + budget categories
+ + category:
+ + "Development",
+ + "Design",
+ + "Marketing",
+ + "Operations",
+ + "Research",
+ + "Community Management",
+ + "Legal",
+ + "Other"
+ + amount
+ + description
+
+**Value for money**
+ + costBenefitAnalysis
+ + longTermValue
+ + communityBenefits
+
+**Mandatory Acknowledgments**
+ + fundRules
+ + acknowledgment
+ + version
+ + timestamp
+ + termsAndConditions
+ + acknowledgment
+ + version
+ + documentUrl
+ + timestamp
+ + privacyPolicy
+ + acknowledgment
+ + version
+ + documentUrl
+ + timestamp
+ + compliance
+ + legalCompliance
+ + noConflictOfInterest
+ + accurateInformation
+ + jurisdictions
+ + timestamp
+ + additionalAcknowledgments
+ + type
+ + acknowledgment
+ + description
+ + documentUrl
+ + timestamp
\ No newline at end of file
From 9422df09a3ee5b59006c3a506215c33365729ee5 Mon Sep 17 00:00:00 2001
From: Nathan Bogale
Date: Thu, 5 Dec 2024 17:16:52 +0300
Subject: [PATCH 10/25] fix: captured all new fields added in this file
---
.../proposal/F14-Generic/readModifications.md | 161 ++++++++++--------
1 file changed, 88 insertions(+), 73 deletions(-)
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/readModifications.md b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/readModifications.md
index 8ca17618a52..055d0b00db9 100644
--- a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/readModifications.md
+++ b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/readModifications.md
@@ -1,60 +1,58 @@
-# F14-Generic
-## Changes to the proposal template fields
+# F14-Generic Proposal Template
+## New Fields added to the proposal template
**Problem:**
- - Statement
- - Impact (select):
- - "Technical Infrastructure",
- - "User Experience",
- - "Developer Tooling",
- - "Community Growth",
- - "Economic Sustainability",
- - "Interoperability",
- - "Security",
- - "Scalability",
- - "Education",
- - "Adoption"
-
-
+ + Statement
+ + Impact (select):
+ + "Technical Infrastructure",
+ + "User Experience",
+ + "Developer Tooling",
+ + "Community Growth",
+ + "Economic Sustainability",
+ + "Interoperability",
+ + "Security",
+ + "Scalability",
+ + "Education",
+ + "Adoption"
**Solution:**
- - summary
- - approach
- - innovative aspects
+ + Summary
+ + Approach
+ + Innovative aspects
**Supporting links:**
- - Links
- - Url
- - Description
- - Type (select):
- - "GitHub Repository",
- - "Documentation",
- - "Whitepaper",
- - "Website",
- - "Marketing Material",
- - "Technical Specification",
- - "Research Paper",
- - "Blog Post",
- - "Social Media",
- - "Other"
- - Main Repository link
- - Documentation link
+ + Links
+ + Url
+ + Description
+ + Type (select):
+ + "GitHub Repository",
+ + "Documentation",
+ + "Whitepaper",
+ + "Website",
+ + "Marketing Material",
+ + "Technical Specification",
+ + "Research Paper",
+ + "Blog Post",
+ + "Social Media",
+ + "Other"
+ + Main Repository link
+ + Documentation link
**Dependencies**
- - detail:
- - name
- - description
- - type:
- - "Technical"
- - "Organizational"
- - "Legal"
- - "Financial"
- - "Other"
- - mitigationPlan
+ + detail:
+ + name
+ + description
+ + type:
+ + "Technical"
+ + "Organizational"
+ + "Legal"
+ + "Financial"
+ + "Other"
+ + mitigationPlan
**Horizons:**
- - tags:
- - additional tags to be entered for the project -> on top of category and subcategory
+ + tags:
+ + additional tags to be entered for the project -> on top of category and subcategory
+ Impact:
+ timeframe:
+ "Short-term (0-6 months)"
@@ -164,29 +162,46 @@
+ communityBenefits
**Mandatory Acknowledgments**
- + fundRules
- + acknowledgment
- + version
- + timestamp
- + termsAndConditions
- + acknowledgment
- + version
- + documentUrl
- + timestamp
- + privacyPolicy
- + acknowledgment
- + version
- + documentUrl
- + timestamp
- + compliance
- + legalCompliance
- + noConflictOfInterest
- + accurateInformation
- + jurisdictions
- + timestamp
- + additionalAcknowledgments
- + type
- + acknowledgment
- + description
- + documentUrl
- + timestamp
\ No newline at end of file
+ + Fund Rules
+ + Acknowledgment
+ + Version
+ + Timestamp
+
+ + Terms And Conditions
+ + Acknowledgment
+ + Version
+ + DocumentUrl
+ + Timestamp
+
+ + Privacy Policy
+ + Acknowledgment
+ + Version
+ + DocumentUrl
+ + Timestamp
+
+ + Intellectual Property
+ + Acknowledgment
+ + Details
+ + Attachments
+ + Document Type
+ + "patent",
+ + "trademark",
+ + "copyright",
+ + "license",
+ + "other"
+ + Document Url
+ + Description
+
+ + Compliances (checkboxes)
+ + Legal Compliance
+ + No Conflict Of Interest
+ + Accurate Information
+ + Jurisdictions
+ + Timestamp
+
+ + Additional Acknowledgments
+ + Type
+ + Acknowledgment
+ + Description
+ + Document Url
+ + Timestamp
\ No newline at end of file
From 3fe083f801f3ea53f710de06873fae32a859845f Mon Sep 17 00:00:00 2001
From: Nathan Bogale
Date: Thu, 5 Dec 2024 19:10:18 +0300
Subject: [PATCH 11/25] fix: updated example proposal
---
...38-9258-4fbc-a62e-7faa6e58318f.schema.json | 6 +-
.../F14-Generic/example.proposal.json | 229 +++++++++++-------
2 files changed, 149 insertions(+), 86 deletions(-)
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
index 36ce520028e..8642ba3ebb3 100644
--- a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
+++ b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
@@ -97,9 +97,7 @@
"description": "Proposal title
Please note we suggest you use no more than 60 characters for your proposal title so that it can be easily viewed in the voting app.
",
"minLength": 1,
"maxLength": 60,
- "examples": [
- "The title should clearly express what the proposal is about. Voters can see the title in the voting app, even without opening the proposal, so a clear, unambiguous, and concise title is very important.
"
- ]
+ "x-guidance": "The title should clearly express what the proposal is about. Voters can see the title in the voting app, even without opening the proposal, so a clear, unambiguous, and concise title is very important.
"
}
},
"required": [
@@ -121,7 +119,7 @@
"$ref": "#/definitions/dropDownSingleSelect",
"title": "Are you delivering this project as an individual or as an entity (whether formally incorporated or not)",
"description": "Are you delivering this project as an individual or as an entity (whether formally incorporated or not)",
- "x-guidance": "Please select from one of the following:
- Individual
- Entity (Incorporated)
- Entity (Not Incorporated)
",
+ "x-mad-guidance": "Please select from one of the following:
- Individual
- Entity (Incorporated)
- Entity (Not Incorporated)
",
"enum": [
"Individual",
"Entity (Incorporated)",
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/example.proposal.json b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/example.proposal.json
index 25a479f83b6..d524fec31ae 100644
--- a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/example.proposal.json
+++ b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/example.proposal.json
@@ -2,141 +2,206 @@
"$schema": "./0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json",
"setup": {
"title": {
- "title": "Cardano DeFi Integration Platform"
+ "title": "Example Catalyst Proposal"
},
"proposer": {
- "mainApplicant": "John Smith",
- "applicantType": "Entity (Incorporated)",
- "coProposers": ["Alice Johnson", "Bob Wilson"]
+ "applicant": "John Doe",
+ "type": "Individual",
+ "coproposers": []
}
},
- "proposalSummary": {
+ "summary": {
"budget": {
- "requestedFunds": 500000
+ "requestedFunds": 150000
+ },
+ "time": {
+ "duration": 6
+ },
+ "translation": {
+ "translated": false,
+ "original": "English",
+ "notes": "Original proposal in English"
},
"problem": {
- "description": "Current DeFi platforms on Cardano lack seamless integration capabilities, making it difficult for developers to build interconnected financial applications.",
- "relevance": "This problem affects the entire Cardano ecosystem by limiting the growth and adoption of DeFi applications."
+ "statement": "Current challenge in the Cardano ecosystem...",
+ "impact": ["Technical Infrastructure", "Developer Tooling", "Adoption"]
+ },
+ "solution": {
+ "summary": "Our solution provides a comprehensive toolkit...",
+ "approach": "We will implement this solution using...",
+ "innovationAspects": [
+ "Novel testing framework",
+ "Automated integration tools"
+ ]
},
- "supportingLinks": {
- "documentation": "https://example.com/project-docs",
- "github": "https://github.com/example/defi-platform",
- "media": ["https://example.com/demo-video"]
+ "SupportingLinks": {
+ "links": [
+ {
+ "url": "https://github.com/example/project",
+ "type": "GitHub Repository",
+ "description": "Project's main repository"
+ }
+ ],
+ "mainRepository": "https://github.com/example/project",
+ "documentation": "https://docs.example.com"
}
},
"horizons": {
"category": {
- "primaryCategory": "DeFi",
+ "primaryCategory": "Development & Tools",
"subCategory": "Developer Tools"
},
- "tags": ["defi", "integration", "developer-tools", "smart-contracts"]
+ "tags": ["defi", "developer-tools", "infrastructure"],
+ "impact": {
+ "timeframe": "Medium-term (6-18 months)",
+ "scale": "Global",
+ "metrics": [
+ {
+ "metric": "Developer Adoption",
+ "target": "500 active developers",
+ "measurement": "GitHub analytics"
+ }
+ ]
+ }
},
"proposalDetails": {
"solution": {
- "description": "Our platform will provide a unified API layer that enables seamless integration between different DeFi protocols on Cardano.",
- "features": [
- "Standardized API endpoints",
- "Smart contract templates",
- "Cross-protocol liquidity management"
- ]
+ "description": "Our solution provides a comprehensive toolkit...",
+ "uniqueValue": "First integrated testing framework for Cardano",
+ "targetAudience": ["Cardano Developers", "DApp Teams"],
+ "implementation": "We will use an agile development approach..."
},
"impact": {
+ "communityBenefit": "Significantly reduces development time and improves code quality",
"metrics": [
- "Number of integrated protocols",
- "Developer adoption rate",
- "Transaction volume through the platform"
+ {
+ "name": "Developer Adoption",
+ "description": "Number of active developers using the toolkit",
+ "target": "500 developers",
+ "measurement": "GitHub analytics and usage statistics"
+ }
],
- "targetAudience": "DeFi developers and protocol creators on Cardano"
+ "outputs": [
+ "Testing Framework",
+ "Documentation",
+ "Training Materials"
+ ]
},
"capability": {
- "teamExperience": "Our team has 5+ years of experience in DeFi development and Cardano ecosystem",
- "resources": "Fully equipped development team with blockchain expertise"
+ "teamExperience": "Our team has extensive experience in blockchain development...",
+ "feasibilityApproach": "We have already developed a proof of concept...",
+ "fundManagement": "Funds will be managed through a transparent process..."
}
},
"milestones": {
"milestonesConfig": {
- "count": 4,
- "duration": "6 months"
+ "grantAmount": 150000,
+ "numberOfMilestones": 4
},
"milestonesList": [
{
- "title": "Architecture Design",
- "description": "Complete system architecture and API specifications",
- "deliverables": ["Architecture documentation", "API specifications"],
- "budget": {
- "amount": 100000
- }
- },
- {
- "title": "Core Development",
- "description": "Develop core integration layer and smart contracts",
- "deliverables": ["Core platform code", "Smart contract templates"],
- "budget": {
- "amount": 200000
- }
- },
- {
- "title": "Testing and Integration",
- "description": "Comprehensive testing and initial protocol integrations",
- "deliverables": ["Test reports", "Integration documentation"],
+ "title": "Initial Setup and Planning",
+ "description": "Project setup and detailed planning phase",
+ "deliverables": [
+ {
+ "name": "Project Plan",
+ "description": "Detailed project planning documentation",
+ "type": "Documentation"
+ }
+ ],
+ "acceptanceCriteria": [
+ "Completed project plan",
+ "Technical specifications approved"
+ ],
+ "evidenceOfCompletion": [
+ {
+ "type": "Documentation",
+ "description": "Project planning documents and specifications"
+ }
+ ],
+ "timeline": {
+ "startDate": "2024-03-01",
+ "endDate": "2024-04-01",
+ "durationInWeeks": 4
+ },
"budget": {
- "amount": 150000
+ "amount": 37500,
+ "breakdown": [
+ {
+ "category": "Development",
+ "amount": 30000,
+ "description": "Initial development work"
+ }
+ ]
}
}
- ],
- "finalMilestone": {
- "title": "Launch and Documentation",
- "deliverables": ["Platform launch", "Complete documentation", "Video demonstration"],
- "budget": {
- "amount": 50000
- }
- }
+ ]
},
"finalPitch": {
"team": {
"members": [
{
- "name": "John Smith",
+ "name": "John Doe",
"role": "Project Lead",
- "experience": "10 years in blockchain development"
- },
- {
- "name": "Alice Johnson",
- "role": "Smart Contract Developer",
- "experience": "5 years Cardano development"
+ "expertise": ["Blockchain Development", "Smart Contracts"],
+ "experience": "10 years in software development",
+ "links": [
+ {
+ "type": "GitHub",
+ "url": "https://github.com/johndoe",
+ "description": "GitHub Profile"
+ }
+ ]
}
- ],
- "teamCapabilities": "Our team combines deep expertise in DeFi protocols, Cardano development, and system architecture."
+ ]
},
"budget": {
- "totalBudget": 500000,
- "categories": {
- "development": 300000,
- "testing": 100000,
- "documentation": 50000,
- "management": 50000
- },
- "timeline": {
- "distributionSchedule": "Quarterly"
- }
+ "totalBudget": 150000,
+ "categories": [
+ {
+ "category": "Development",
+ "amount": 100000,
+ "description": "Core development team costs"
+ }
+ ]
},
"valueProposition": {
- "impact": "Accelerate DeFi development on Cardano",
- "sustainability": "Platform fees and maintenance contracts"
+ "costBenefitAnalysis": "The project provides significant value...",
+ "longTermValue": "The solution will continue to benefit the ecosystem...",
+ "communityBenefits": [
+ "Increased developer productivity",
+ "Better code quality"
+ ]
}
},
"mandatoryAcknowledgments": {
"fundRules": {
- "acknowledgment": true
+ "acknowledgment": true,
+ "version": "F14",
+ "timestamp": "2024-01-20T15:30:00Z"
+ },
+ "termsAndConditions": {
+ "acknowledgment": true,
+ "version": "1.0.0",
+ "documentUrl": "https://cardano.org/terms",
+ "timestamp": "2024-01-20T15:30:00Z"
},
"privacyPolicy": {
- "acknowledgment": true
+ "acknowledgment": true,
+ "version": "1.0.0",
+ "documentUrl": "https://cardano.org/privacy",
+ "timestamp": "2024-01-20T15:30:00Z"
},
"intellectualProperty": {
- "acknowledgment": true
+ "acknowledgment": true,
+ "timestamp": "2024-01-20T15:30:00Z"
},
"compliance": {
- "legalCompliance": true
+ "legalCompliance": true,
+ "noConflictOfInterest": true,
+ "accurateInformation": true,
+ "jurisdictions": ["US", "GB"],
+ "timestamp": "2024-01-20T15:30:00Z"
}
}
-}
+}
\ No newline at end of file
From a07f3bcfdf073e3614ed0196651ff441ea4bb3c9 Mon Sep 17 00:00:00 2001
From: Steven Johnson
Date: Fri, 6 Dec 2024 08:17:25 +0700
Subject: [PATCH 12/25] fix(cat-gateway): rename section breaks to align with
design
---
...38-9258-4fbc-a62e-7faa6e58318f.schema.json | 22 +++++++++----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
index 36ce520028e..874ba784814 100644
--- a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
+++ b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
@@ -10,12 +10,12 @@
"format": "path",
"readOnly": true
},
- "section": {
+ "segment": {
"$comment": "UI - Logical Document Section Break.",
"type": "object",
"additionalProperties": false
},
- "subsection": {
+ "section": {
"$comment": "UI - Logical Document Sub-Section Break.",
"type": "object",
"additionalProperties": false
@@ -82,12 +82,12 @@
"const": "./0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json"
},
"setup": {
- "$ref": "#/definitions/section",
+ "$ref": "#/definitions/segment",
"title": "proposal setup",
"description": "Proposal title",
"properties": {
"title": {
- "$ref": "#/definitions/subsection",
+ "$ref": "#/definitions/section",
"title": "proposal setup",
"description": "Proposal title",
"properties": {
@@ -107,7 +107,7 @@
]
},
"proposer": {
- "$ref": "#/definitions/subsection",
+ "$ref": "#/definitions/section",
"properties": {
"applicant": {
"$ref": "#/definitions/singleLineTextEntry",
@@ -150,12 +150,12 @@
]
},
"summary": {
- "$ref": "#/definitions/section",
+ "$ref": "#/definitions/segment",
"title": "Proposal Summary",
"description": "Key information about your proposal",
"properties": {
"budget": {
- "$ref": "#/definitions/subsection",
+ "$ref": "#/definitions/section",
"title": "Budget Information",
"properties": {
"requestedFunds": {
@@ -172,7 +172,7 @@
]
},
"time": {
- "$ref": "#/definitions/subsection",
+ "$ref": "#/definitions/section",
"properties": {
"duration": {
"$ref": "#/definitions.durationInMonths",
@@ -188,7 +188,7 @@
]
},
"translation": {
- "$ref": "#/definitions/subsection",
+ "$ref": "#/definitions/section",
"title": "Translation Information",
"description": "Information about the proposal's language and translation status",
"properties": {
@@ -242,7 +242,7 @@
}
},
"problem": {
- "$ref": "#/definitions/subsection",
+ "$ref": "#/definitions/section",
"title": "Problem Statement",
"description": "Define the problem your proposal aims to solve",
"properties": {
@@ -283,7 +283,7 @@
]
},
"solution": {
- "$ref": "#/definitions/subsection",
+ "$ref": "#/definitions/section",
"title": "Solution Overview",
"description": "Describe your proposed solution to the problem",
"properties": {
From 5eee04d94d798b0bc65dad725c6ebba3338de57c Mon Sep 17 00:00:00 2001
From: Steven Johnson
Date: Fri, 6 Dec 2024 13:23:26 +0700
Subject: [PATCH 13/25] docs(cat-gateway): Finish the template as at F13 state
---
.config/dictionaries/project.dic | 2 +
...38-9258-4fbc-a62e-7faa6e58318f.schema.json | 11 +-
...38-9258-4fbc-a62e-7faa6e58318f.schema.json | 1780 +++++------------
.../F14-Generic/example.proposal.json | 39 +-
.../F14-Generic/extra-definitions.txt | 1079 ++++++++++
.../proposal/F14-Generic/readModifications.md | 374 ++--
6 files changed, 1796 insertions(+), 1489 deletions(-)
create mode 100644 docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/extra-definitions.txt
diff --git a/.config/dictionaries/project.dic b/.config/dictionaries/project.dic
index 517820b0998..bd4d4cd78dc 100644
--- a/.config/dictionaries/project.dic
+++ b/.config/dictionaries/project.dic
@@ -50,6 +50,7 @@ chrono
ciphertext
ciphertexts
CIPs
+CNFT
COCOAPODS
codegen
codepoints
@@ -109,6 +110,7 @@ gethostname
Gitbook
gmtime
gradlew
+Hackathons
headful
headlessui
HIDPI
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic-Steven/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic-Steven/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
index 63abfbcede2..831508f8194 100644
--- a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic-Steven/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
+++ b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic-Steven/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
@@ -38,16 +38,19 @@
"format": "yes/no",
"default": false
},
+ "uri": {
+ "type": "string",
+ "format": "uri",
+ "contentMediaType": "text/plain",
+ "maxLength": 1024
+ },
"uriList": {
"type": "array",
"format": "uriList",
"uniqueItems": true,
"default": [],
"items": {
- "type": "string",
- "format": "uri",
- "contentMediaType": "text/plain",
- "maxLength": 1024
+ "$ref": "#/definitions/uri"
}
}
},
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
index 9315bc8281c..dc5812c5be1 100644
--- a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
+++ b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
@@ -26,11 +26,23 @@
"contentMediaType": "text/plain",
"pattern": "^.*$"
},
+ "singleLineHttpsURLEntry": {
+ "$comment": "UI - Single Line text entry for HTTPS Urls.",
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https:.*"
+ },
"multiLineTextEntry": {
"$comment": "UI - Multiline text entry without any markup or rich text capability.",
"type": "string",
"contentMediaType": "text/plain",
- "pattern": "^[\\S\\s]$"
+ "pattern": "^[\\S\\s]*$"
+ },
+ "multiLineTextEntryMarkdown": {
+ "$comment": "UI - Multiline text entry with Markdown content.",
+ "type": "string",
+ "contentMediaType": "text/markdown",
+ "pattern": "^[\\S\\s]*$"
},
"dropDownSingleSelect": {
"$comment": "UI - Drop Down Selection of a single entry from the defined enum.",
@@ -56,6 +68,59 @@
"maxLength": 1024
}
},
+ "multiLineTextEntryListMarkdown": {
+ "$comment": "UI - A Growable List of markdown formatted text fields.",
+ "type": "array",
+ "format": "multiLineTextEntryListMarkdown",
+ "uniqueItems": true,
+ "default": [],
+ "items": {
+ "$ref": "#/definitions/multiLineTextEntryMarkdown",
+ "maxLength": 10240
+ }
+ },
+ "singleLineHttpsURLEntryList": {
+ "$comment": "UI - A Growable List of HTTPS URLs.",
+ "type": "array",
+ "format": "singleLineHttpsURLEntryList",
+ "uniqueItems": true,
+ "default": [],
+ "items": {
+ "$ref": "#/definitions/singleLineHttpsURLEntry",
+ "maxLength": 1024
+ }
+ },
+ "nestedQuestionsList": {
+ "$comment": "UI - A Growable List of Questions. The contents are an object, that can have any UI elements within.",
+ "type": "array",
+ "format": "nestedQuestionsList",
+ "uniqueItems": true,
+ "default": []
+ },
+ "nestedQuestions": {
+ "$comment": "UI - The container for a nested question set.",
+ "type": "object",
+ "format": "nestedQuestions",
+ "additionalProperties": false
+ },
+ "singleGroupedTagSelector": {
+ "$comment": "UI - A selector where a top level selection, gives a single choice from a list of tags.",
+ "type": "object",
+ "format": "singleGroupedTagSelector",
+ "additionalProperties": false
+ },
+ "tagGroup": {
+ "$comment": "UI - An individual group within a singleGroupedTagSelector.",
+ "type": "string",
+ "format": "tagGroup",
+ "pattern": "^.*$"
+ },
+ "tagSelection": {
+ "$comment": "UI - An individual tag within the group of a singleGroupedTagSelector.",
+ "type": "string",
+ "format": "tagSelection",
+ "pattern": "^.*$"
+ },
"tokenValueCardanoADA": {
"$comment": "UI - A Token Value denominated in Cardano ADA.",
"type": "integer",
@@ -69,8 +134,22 @@
"yesNoChoice": {
"$comment": "UI - A Boolean choice, represented as a Yes/No selection. Yes = true.",
"type": "boolean",
- "format": "yes/no",
+ "format": "yesNoChoice",
"default": false
+ },
+ "agreementConfirmation": {
+ "$comment": "UI - A Boolean choice, defaults to `false` but its invalid if its not set to `true`.",
+ "type": "boolean",
+ "format": "agreementConfirmation",
+ "default": false,
+ "const": true
+ },
+ "spdxLicenseOrURL": {
+ "$comment": "UI - Drop Down Selection of any valid SPDX Identifier. This is a complex type, it should let the user select one of the valid SPDX licenses, or enter a URL of the license if its proprietary. In the form its just a string.",
+ "type": "string",
+ "contentMediaType": "text/plain",
+ "pattern": "^.*$",
+ "format": "spdxLicenseOrURL"
}
},
"type": "object",
@@ -131,7 +210,7 @@
"$ref": "#/definitions/singleLineTextEntryList",
"title": "Co-proposers and additional applicants",
"description": "Co-proposers and additional applicants",
- "x-guidance": "List any persons who are submitting the proposal jointly with the main applicant. Make sure you have confirmed approval/awareness with these individuals/accounts before adding them. If there is more than one proposer, identify the lead person who is authorized to act on behalf of other co-proposers. IMPORTANT A maximum of 6 (six) proposals can be led or co-proposed by the same applicant or enterprise. Please, reference Fund 13 rules for added detail.
",
+ "x-guidance": "List any persons who are submitting the proposal jointly with the main applicant. Make sure you have confirmed approval/awareness with these individuals/accounts before adding them. If there is more than one proposer, identify the lead person who is authorized to act on behalf of other co-proposers. IMPORTANT A maximum of 6 (six) proposals can be led or co-proposed by the same applicant or enterprise. Please, reference Fund 14 rules for added detail.
",
"maxItems": 5,
"minItems": 0
}
@@ -173,7 +252,7 @@
"$ref": "#/definitions/section",
"properties": {
"duration": {
- "$ref": "#/definitions.durationInMonths",
+ "$ref": "#/definitions/durationInMonths",
"title": "Project Duration in Months",
"description": "Specify the expected duration of your project. Projects must be completable within 2-12 months.",
"x-guidance": "Minimum 2 months-Maximum 12 months. The scope of your funding request and this project is expected to produce the deliverables you specify in the proposal within 2-12 months If you believe your project will take longer than 12 months, consider reducing the project's scope so that it becomes achievable within 12 months If your project completes earlier than scheduled so long as you have submitted your PoAs and Project Close-out report and video then your project can be closed out.
",
@@ -182,7 +261,7 @@
}
},
"required": [
- "projectDuration"
+ "duration"
]
},
"translation": {
@@ -257,7 +336,7 @@
"title": "Impact Areas",
"description": "Select the areas that will be most impacted by solving this problem",
"items": {
- "$ref": "singleLineTextEntry",
+ "$ref": "#/definitions/singleLineTextEntry",
"enum": [
"Technical Infrastructure",
"User Experience",
@@ -291,29 +370,20 @@
"description": "Briefly describe your solution. Focus on what you will do or create to solve the problem.",
"minLength": 10,
"maxLength": 200,
- "x-guidance":"Focus on what you are going to do, or make, or change, to solve the problem. So not 'There should be a way to....' but 'We will make a Clearly state how the solution addresses the specific problem you have identified - connect the 'why' and the 'how' This answer will be displayed on the Catalyst voting app, so voters will see it even if they do not open your proposal and read it in detail.
"
+ "x-guidance": "Focus on what you are going to do, or make, or change, to solve the problem. So not 'There should be a way to....' but 'We will make a Clearly state how the solution addresses the specific problem you have identified - connect the 'why' and the 'how' This answer will be displayed on the Catalyst voting app, so voters will see it even if they do not open your proposal and read it in detail.
"
},
"approach": {
- "type": "string",
+ "$ref": "#/definitions/multiLineTextEntry",
"title": "Technical Approach",
"description": "Outline the technical approach or methodology you will use",
- "maxLength": 500,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
+ "maxLength": 500
},
"innovationAspects": {
- "type": "array",
+ "$ref": "#/definitions/singleLineTextEntryList",
"title": "Innovation Aspects",
"description": "Key innovative aspects of your solution",
- "items": {
- "type": "string",
- "maxLength": 100,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- },
"minItems": 1,
- "maxItems": 5,
- "uniqueItems": true
+ "maxItems": 5
}
},
"required": [
@@ -322,145 +392,72 @@
]
},
"SupportingLinks": {
- "type": "object",
+ "$ref": "#/definitions/section",
"title": "Supporting Documentation",
"description": "Additional resources and documentation for your proposal",
+ "x-guidance": "Here, provide links to yours or your partner organization's website, repository, or marketing. Alternatively, provide links to any whitepaper or other publication relevant to your proposal. Note however that this is extra information that voters and Community Reviewers might choose not to read. You should not fail to include any of the questions in this form because you feel the answers can be found elsewhere. If any links are specified make sure these are added in good order (first link must be present before specifying second). Also ensure all links include https. Without these steps, the form will not be submittable and show errors
",
"properties": {
- "links": {
- "type": "array",
- "title": "Resource Links",
- "description": "Links to relevant documentation, code repositories, or marketing materials. All links must use HTTPS.",
- "x-guidance": "Here, provide links to yours or your partner organization's website, repository, or marketing. Alternatively, provide links to any whitepaper or other publication relevant to your proposal. Note however that this is extra information that voters and Community Reviewers might choose not to read. You should not fail to include any of the questions in this form because you feel the answers can be found elsewhere. If any links are specified make sure these are added in good order (first link must be present before specifying second). Also ensure all links include https. Without these steps, the form will not be submittable and show errors
",
- "items": {
- "type": "object",
- "properties": {
- "url": {
- "type": "string",
- "format": "uri",
- "pattern": "^https://.*",
- "title": "Resource URL",
- "description": "URL must start with https://",
- "examples": [
- "https://github.com/your-org/project",
- "https://your-project-docs.com"
- ],
- "pattern": "^https?://[\\w\\-]+(\\.[\\w\\-]+)+[/#?]?.*$",
- "contentMediaType": "text/uri-list"
- },
- "type": {
- "type": "string",
- "enum": [
- "GitHub Repository",
- "Documentation",
- "Whitepaper",
- "Website",
- "Marketing Material",
- "Technical Specification",
- "Research Paper",
- "Blog Post",
- "Social Media",
- "Other"
- ],
- "title": "Resource Type",
- "description": "Type of resource being linked"
- },
- "description": {
- "type": "string",
- "maxLength": 200,
- "title": "Resource Description",
- "description": "Brief description explaining what this resource contains and why it's relevant",
- "examples": [
- "Project's main GitHub repository containing all source code",
- "Technical whitepaper detailing the solution architecture"
- ],
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- }
- },
- "required": [
- "url",
- "type",
- "description"
- ]
- },
- "minItems": 0,
- "maxItems": 10,
- "uniqueItems": true
- },
"mainRepository": {
- "type": "string",
- "format": "uri",
- "pattern": "^https://(github\\.com|gitlab\\.com|bitbucket\\.org)/.*",
+ "$ref": "#/definitions/singleLineHttpsURLEntry",
"title": "Main Code Repository",
- "description": "Primary repository where the project's code will be hosted",
- "pattern": "^https?://[\\w\\-]+(\\.[\\w\\-]+)+[/#?]?.*$",
- "contentMediaType": "text/uri-list"
+ "description": "Primary repository where the project's code will be hosted"
},
"documentation": {
- "type": "string",
- "format": "uri",
- "pattern": "^https://.*",
+ "$ref": "#/definitions/singleLineHttpsURLEntry",
"title": "Documentation URL",
- "description": "Main documentation site or resource for the project",
- "pattern": "^https?://[\\w\\-]+(\\.[\\w\\-]+)+[/#?]?.*$",
- "contentMediaType": "text/uri-list"
+ "description": "Main documentation site or resource for the project"
+ },
+ "other": {
+ "$ref": "#/definitions/singleLineHttpsURLEntryList",
+ "title": "Resource Links",
+ "description": "Links to any other relevant documentation, code repositories, or marketing materials. All links must use HTTPS.",
+ "minItems": 0,
+ "maxItems": 5
}
}
},
"dependencies": {
- "type": "object",
+ "$ref": "#/definitions/section",
"title": "Project Dependencies",
"description": "External dependencies and requirements for project success",
+ "x-guidance": "If your project has any dependencies and prerequisites for your project's success, list them here. These are usually external factors (such as third-party suppliers, external resources, third-party software, etc.) that may cause a delay, since a project has less control over them. In case of third party software, indicate whether you have the necessary licenses and permission to use such software.
",
"properties": {
- "hasDependencies": {
- "type": "boolean",
- "title": "Has Dependencies",
- "description": "Indicate if your project has any dependencies on other organizations or technologies",
- "default": false
- },
"details": {
- "type": "array",
+ "$ref": "#/definitions/nestedQuestionsList",
"title": "Dependency Details",
"description": "List and describe each dependency",
- "x-guidance": "Here you should list any dependencies and prerequisites for your project's success. These are usually external factors (such as third-party suppliers, external resources, third-party software, etc.) that may cause a delay, since a project has less control over them. In case of third party software, indicate whether you have the necessary licenses and permission to use such software.
",
"items": {
- "type": "object",
+ "$ref": "#/definitions/nestedQuestions",
"properties": {
"name": {
- "type": "string",
+ "$ref": "#/definitions/singleLineTextEntry",
"title": "Dependency Name",
"description": "Name of the organization, technology, or resource",
- "maxLength": 100,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
+ "maxLength": 100
},
"type": {
- "type": "string",
+ "$ref": "#/definitions/dropDownSingleSelect",
+ "title": "Dependency Type",
+ "description": "Type of dependency",
"enum": [
"Technical",
"Organizational",
"Legal",
"Financial",
"Other"
- ],
- "title": "Dependency Type",
- "description": "Type of dependency"
+ ]
},
"description": {
- "type": "string",
+ "$ref": "#/definitions/multiLineTextEntry",
"title": "Description",
"description": "Explain why this dependency is essential and how it affects your project",
- "maxLength": 500,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
+ "maxLength": 500
},
"mitigationPlan": {
- "type": "string",
+ "$ref": "#/definitions/multiLineTextEntry",
"title": "Mitigation Plan",
"description": "How will you handle potential issues with this dependency",
- "maxLength": 300,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
+ "maxLength": 300
}
},
"required": [
@@ -472,1259 +469,448 @@
"minItems": 0,
"maxItems": 10
}
- },
- "required": [
- "hasDependencies"
- ],
- "dependencies": {
- "details": [
- "hasDependencies"
- ]
- },
- "if": {
- "properties": {
- "hasDependencies": {
- "const": true
- }
- }
- },
- "then": {
- "required": [
- "details"
- ]
}
},
"open_source": {
+ "$ref": "#/definitions/section",
"title": "Project Open Source",
"description": "Will your project's output/be s fully open source? Open source refers to something people can modify and share because its design is publicly accessible.",
- "x-guidance":"Open source software is software with source code that anyone can inspect, modify, and enhance. Conversely, only the original authors of proprietary software can legally copy, inspect, and alter that software
",
+ "x-guidance": "Open source software is software with source code that anyone can inspect, modify, and enhance. Conversely, only the original authors of proprietary software can legally copy, inspect, and alter that software
",
"properties": {
- "open_source": {
- "$ref": "#/definitions/yesNoChoice",
- "title": "Is Project Open Source?",
- "description": "Will your project's output/be s fully open source? Open source refers to something people can modify and share because its design is publicly accessible.",
- "x-guidance": "Open source software is software with source code that anyone can inspect, modify, and enhance. Conversely, only the original authors of proprietary software can legally copy, inspect, and alter that software
"
+ "source_code": {
+ "$ref": "#/definitions/spdxLicenseOrURL"
},
- "more_information": {
+ "documentation": {
+ "$ref": "#/definitions/spdxLicenseOrURL"
+ },
+ "note": {
"$ref": "#/definitions/multiLineTextEntry",
"title": "More Information",
"description": "Please provide here more information on the open source status of your project outputs",
"maxLength": 500,
- "x-guidance": "If you answered YES to the above question If declaring the project is open source in the application form, the project should be open source-available throughout the entire lifecycle of the project with a declared open-source repository. Please indicate here the type of license you intend to use for open source and provide any further information you feel is relevant to the open source status of your project outputs If only certain elements of your code will be open source please clarify which elements will be open source here. If you answered NO to the above question, please give further details as to why your projects outputs will not be open source METADATA
"
+ "x-guidance": "If you did not answer PROPRIETARY to the above questions, the project should be open source-available throughout the entire lifecycle of the project with a declared open-source repository. Please indicate here the type of license you intend to use for open source and provide any further information you feel is relevant to the open source status of your project outputs If only certain elements of your code will be open source please clarify which elements will be open source here. If you answered NO to the above question, please give further details as to why your projects outputs will not be open source METADATA
"
}
},
"required": [
- "isOpenSource"
- ],
- "dependencies": {
- "open_source": [
- "isOpenSource"
- ],
- "more_information": [
- "isOpenSource"
- ]
- },
- "if": {
- "properties": {
- "isOpenSource": {
- "const": true
- }
- }
- },
- "then": {
- "required": [
- "more_information"
- ]
- }
+ "source_code",
+ "documentation"
+ ]
}
}
},
"horizons": {
- "type": "object",
- "title": "Project Horizons",
- "description": "Long-term vision and categorization of your project",
+ "$ref": "#/definitions/segment",
+ "title": "Horizons",
"properties": {
- "category": {
- "type": "object",
- "title": "Project Category",
- "description": "Select the most relevant category and tags for your project",
- "x-guidance": "Please choose the most relevant category group and tag related to the outcomes of your proposal. Can select only one group and one tag.
",
- "properties": {
- "primaryCategory": {
- "type": "string",
- "title": "Primary Category",
- "description": "Main category that best describes your project",
- "enum": [
- "Governance",
- "Education",
- "Community & Outreach",
- "Development & Tools",
- "Identity & Security",
- "DeFi",
- "Real World Applications",
- "Events & Marketing",
- "Interoperability",
- "Legal & Policy",
- "Sustainability",
- "Smart Contracts"
- ]
- },
- "subCategory": {
- "type": "string",
- "title": "Sub-category",
- "description": "Specific area within the main category",
- "enum": [
- "DAO",
- "Voting",
- "Treasury Management",
- "Learn to Earn",
- "Training",
- "Translation",
- "Connected Community",
- "Social Media",
- "Community Building",
- "Developer Tools",
- "L2 Infrastructure",
- "Analytics",
- "AI Research",
- "UTXO",
- "P2P",
- "Identity & Verification",
- "Cybersecurity",
- "Authentication",
- "Privacy",
- "Payments",
- "Stablecoin",
- "Risk Management",
- "Yield",
- "Staking",
- "Lending",
- "Wallet",
- "Marketplace",
- "Manufacturing",
- "IoT",
- "Financial Services",
- "E-commerce",
- "Business Services",
- "Supply Chain",
- "Real Estate",
- "Healthcare",
- "Tourism",
- "Entertainment",
- "RWA",
- "Music",
- "Tokenization",
- "Events",
- "Marketing",
- "Hackathons",
- "Accelerator",
- "Incubator",
- "Cross-chain",
- "Off-chain",
- "Bridges",
- "Policy",
- "Advocacy",
- "Standards",
- "Compliance",
- "Environment",
- "Agriculture",
- "Clean Energy",
- "Development",
- "Security",
- "Templates",
- "Auditing"
- ]
- }
- }
- },
- "tags": {
- "type": "array",
- "title": "Project Tags",
- "description": "Additional tags to help categorize your project",
- "items": {
- "type": "string",
- "minLength": 2,
- "maxLength": 30,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- },
- "minItems": 1,
- "maxItems": 5,
- "uniqueItems": true
- },
- "impact": {
- "type": "object",
- "title": "Project Impact",
- "description": "Describe the expected impact of your project",
+ "theme": {
+ "$ref": "#/definitions/section",
+ "title": "Horizons",
+ "description": "Long-term vision and categorization of your project",
"properties": {
- "timeframe": {
- "type": "string",
- "enum": [
- "Short-term (0-6 months)",
- "Medium-term (6-18 months)",
- "Long-term (18+ months)"
- ],
- "title": "Impact Timeframe",
- "description": "Expected timeframe to see meaningful impact"
- },
- "scale": {
- "type": "string",
- "enum": [
- "Local",
- "Regional",
- "Global"
- ],
- "title": "Impact Scale",
- "description": "Geographic scale of impact"
- },
- "metrics": {
- "type": "array",
- "title": "Impact Metrics",
- "description": "Key metrics to measure project success",
- "items": {
- "type": "object",
- "properties": {
- "metric": {
- "type": "string",
- "title": "Metric Name",
- "description": "Name of the metric",
- "maxLength": 100,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- },
- "target": {
- "type": "string",
- "title": "Target Value",
- "description": "Target value or goal for this metric",
- "maxLength": 100,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- },
- "measurement": {
- "type": "string",
- "title": "Measurement Method",
- "description": "How this metric will be measured",
- "maxLength": 200,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
+ "grouped_tag": {
+ "$ref": "#/definitions/singleGroupedTagSelector",
+ "oneOf": [
+ {
+ "properties": {
+ "group": {
+ "$ref": "#/definitions/tagGroup",
+ "const": "Governance"
+ },
+ "tag": {
+ "$ref": "#/definitions/tagSelection",
+ "enum": [
+ "Governance",
+ "DAO"
+ ]
+ }
}
},
- "required": [
- "metric",
- "target",
- "measurement"
- ]
- },
- "minItems": 1,
- "maxItems": 5
- }
- },
- "required": [
- "timeframe",
- "scale",
- "metrics"
- ]
- }
- },
- "required": [
- "primaryCategory",
- "subCategory",
- "tags",
- "impact"
- ]
- },
- "proposalDetails": {
- "type": "object",
- "title": "Proposal Details",
- "description": "Detailed information about your proposal's solution, impact, and feasibility",
- "properties": {
- "solution": {
- "type": "object",
- "title": "Solution Description",
- "description": "Detailed description of your proposed solution",
- "x-guidance": "YOUR PROJECT AND SOLUTION
How you write this section will depend on what type of proposal you are writing. You might want to include details on:
- How do you perceive the problem you are solving?
- What are your reasons for approaching it in the way that you have?
- Who will your project engage?
- How will you demonstrate or prove your impact?
Explain what is unique about your solution, who will benefit, and why this is important to Cardano.
",
- "properties": {
- "description": {
- "type": "string",
- "title": "Solution Description",
- "description": "Provide a comprehensive description of your proposed solution",
- "minLength": 100,
- "maxLength": 2000,
- "examples": [
- "Our solution involves developing a decentralized education platform that will..."
- ],
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- },
- "uniqueValue": {
- "type": "string",
- "title": "Unique Value Proposition",
- "description": "What makes your solution unique and innovative?",
- "minLength": 50,
- "maxLength": 500,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- },
- "targetAudience": {
- "type": "array",
- "title": "Target Audience",
- "description": "Who will benefit from your solution?",
- "items": {
- "type": "string",
- "minLength": 5,
- "maxLength": 100,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- },
- "minItems": 1,
- "maxItems": 5,
- "uniqueItems": true
- },
- "implementation": {
- "type": "string",
- "title": "Implementation Approach",
- "description": "How will you implement your solution?",
- "minLength": 100,
- "maxLength": 1000,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- }
- },
- "required": [
- "description",
- "uniqueValue",
- "targetAudience",
- "implementation"
- ]
- },
- "impact": {
- "type": "object",
- "title": "Project Impact",
- "description": "Define and measure the impact of your project",
- "x-guidance": "Please include here a description of how you intend to measure impact (whether quantitative or qualitative) and how and with whom you will share your outputs:
- In what way will the success of your project bring value to the Cardano Community?
- How will you measure this impact?
- How will you share the outputs and opportunities that result from your project?
",
- "properties": {
- "communityBenefit": {
- "type": "string",
- "title": "Community Benefit",
- "description": "How will the Cardano community benefit from your project?",
- "minLength": 100,
- "maxLength": 1000,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- },
- "metrics": {
- "type": "array",
- "title": "Impact Metrics",
- "description": "Specific metrics to measure project success",
- "items": {
- "type": "object",
- "properties": {
- "name": {
- "type": "string",
- "title": "Metric Name",
- "minLength": 5,
- "maxLength": 100,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- },
- "description": {
- "type": "string",
- "title": "Metric Description",
- "minLength": 20,
- "maxLength": 300,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- },
- "target": {
- "type": "string",
- "title": "Target Value",
- "minLength": 1,
- "maxLength": 100,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- },
- "measurement": {
- "type": "string",
- "title": "Measurement Method",
- "minLength": 20,
- "maxLength": 300,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
+ {
+ "properties": {
+ "group": {
+ "$ref": "#/definitions/tagGroup",
+ "const": "Education"
+ },
+ "tag": {
+ "$ref": "#/definitions/tagSelection",
+ "enum": [
+ "Education",
+ "Learn to Earn",
+ "Training",
+ "Translation"
+ ]
+ }
}
},
- "required": [
- "name",
- "description",
- "target",
- "measurement"
- ]
- },
- "minItems": 2,
- "maxItems": 5
- },
- "outputs": {
- "type": "array",
- "title": "Project Outputs",
- "description": "Tangible outputs and deliverables from the project",
- "items": {
- "type": "string",
- "minLength": 10,
- "maxLength": 200,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- },
- "minItems": 1,
- "maxItems": 10,
- "uniqueItems": true
- }
- },
- "required": [
- "communityBenefit",
- "metrics",
- "outputs"
- ]
- },
- "capability": {
- "type": "object",
- "title": "Capability & Feasibility",
- "description": "Demonstrate your ability to deliver the project successfully",
- "x-guidance":"Please describe your existing capabilities that demonstrate how and why you believe you're best suited to deliver this project? Please include the steps or processes that demonstrate that you can be trusted to manage funds properly.
",
- "properties": {
- "teamExperience": {
- "type": "string",
- "title": "Team Experience",
- "description": "Describe your team's relevant experience and capabilities",
- "minLength": 100,
- "maxLength": 1000,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- },
- "feasibilityApproach": {
- "type": "string",
- "title": "Feasibility Approach",
- "description": "How will you validate the feasibility of your approach?",
- "minLength": 100,
- "maxLength": 1000,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- },
- "fundManagement": {
- "type": "string",
- "title": "Fund Management",
- "description": "How will you ensure proper management and accountability of funds?",
- "minLength": 100,
- "maxLength": 1000,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- }
- },
- "required": [
- "teamExperience",
- "feasibilityApproach",
- "fundManagement"
- ]
- }
- },
- "required": [
- "solution",
- "impact",
- "capability"
- ]
- },
- "milestones": {
- "type": "object",
- "title": "Project Milestones",
- "description": "Detailed project milestones and deliverables",
- "x-guidance": "A clear set of milestones and acceptance criteria will demonstrate your capability to deliver the project as proposed. More guidance on submitting milestones as part of your project proposal can be found here
For Grant Amounts of up to 75k ada, at least 2 milestones, plus the final one including Project Close-out Report and Video, must be included (3 milestones in total)
For Grant Amounts over 75k ada up to 150k ada, at least 3 milestones, plus the final one including Project Close-out Report and Video, must be included (4 milestones in total)
For Grant Amounts over 150k ada up to 300k ada, at least 4 milestones, plus the final one including Project Close-out Report and Video, must be included (5 milestones in total)
For Grant Amounts exceeding 300k ada, at least 5 milestones, plus the final one including Project Close-out Report and Video, must be included (6 milestones in total)
",
- "properties": {
- "milestonesConfig": {
- "type": "object",
- "title": "Milestones Configuration",
- "description": "Configuration for number of milestones",
- "properties": {
- "grantAmount": {
- "type": "number",
- "title": "Grant Amount in ADA",
- "description": "Total grant amount requested in ADA",
- "minimum": 0,
- "maximum": 1000000
- },
- "numberOfMilestones": {
- "type": "integer",
- "title": "Number of Milestones",
- "description": "Total number of milestones including the final milestone",
- "minimum": 2,
- "maximum": 6
- }
- },
- "required": [
- "grantAmount",
- "numberOfMilestones"
- ]
- },
- "milestonesList": {
- "type": "array",
- "title": "List of Milestones",
- "description": "Detailed description of each project milestone",
- "items": {
- "type": "object",
- "title": "Milestone",
- "properties": {
- "title": {
- "type": "string",
- "title": "Milestone Title",
- "description": "Short, descriptive title for the milestone",
- "minLength": 5,
- "maxLength": 100,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- },
- "description": {
- "type": "string",
- "title": "Milestone Description",
- "description": "Detailed description of what this milestone entails",
- "minLength": 50,
- "maxLength": 1000,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- },
- "deliverables": {
- "type": "array",
- "title": "Deliverables",
- "description": "Specific outputs and deliverables for this milestone",
- "items": {
- "type": "object",
+ {
"properties": {
- "name": {
- "type": "string",
- "title": "Deliverable Name",
- "minLength": 5,
- "maxLength": 100,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
+ "group": {
+ "$ref": "#/definitions/tagGroup",
+ "const": "Community & Outreach"
},
- "description": {
- "type": "string",
- "title": "Deliverable Description",
- "minLength": 20,
- "maxLength": 500,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
+ "tag": {
+ "$ref": "#/definitions/tagSelection",
+ "enum": [
+ "Connected Community",
+ "Community",
+ "Community Outreach",
+ "Social Media"
+ ]
+ }
+ }
+ },
+ {
+ "properties": {
+ "group": {
+ "$ref": "#/definitions/tagGroup",
+ "const": "Development & Tools"
},
- "type": {
- "type": "string",
+ "tag": {
+ "$ref": "#/definitions/tagSelection",
"enum": [
- "Documentation",
- "Software",
- "Report",
- "Presentation",
- "Video",
- "Other"
+ "Developer Tools",
+ "L2",
+ "Infrastructure",
+ "Analytics",
+ "AI",
+ "Research",
+ "UTXO",
+ "P2P"
]
}
- },
- "required": [
- "name",
- "description",
- "type"
- ]
+ }
},
- "minItems": 1,
- "maxItems": 5
- },
- "acceptanceCriteria": {
- "type": "array",
- "title": "Acceptance Criteria",
- "description": "Specific criteria that must be met to consider this milestone complete",
- "items": {
- "type": "string",
- "minLength": 10,
- "maxLength": 200,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
+ {
+ "properties": {
+ "group": {
+ "$ref": "#/definitions/tagGroup",
+ "const": "Identity & Security"
+ },
+ "tag": {
+ "$ref": "#/definitions/tagSelection",
+ "enum": [
+ "Identity & Verification",
+ "Cybersecurity",
+ "Security",
+ "Authentication",
+ "Privacy"
+ ]
+ }
+ }
},
- "minItems": 1,
- "maxItems": 5
- },
- "evidenceOfCompletion": {
- "type": "array",
- "title": "Evidence of Completion",
- "description": "How will you demonstrate that this milestone is complete?",
- "items": {
- "type": "object",
+ {
"properties": {
- "type": {
- "type": "string",
- "title": "Evidence Type",
+ "group": {
+ "$ref": "#/definitions/tagGroup",
+ "const": "DeFi"
+ },
+ "tag": {
+ "$ref": "#/definitions/tagSelection",
"enum": [
- "Code Repository",
- "Documentation",
- "Demo Video",
- "Test Results",
- "Metrics Report",
- "User Feedback",
- "Other"
+ "DeFi",
+ "Payments",
+ "Stablecoin",
+ "Risk Management",
+ "Yield",
+ "Staking",
+ "Lending"
]
+ }
+ }
+ },
+ {
+ "properties": {
+ "group": {
+ "$ref": "#/definitions/tagGroup",
+ "const": "Real World Applications"
},
- "description": {
- "type": "string",
- "title": "Evidence Description",
- "minLength": 20,
- "maxLength": 300,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
+ "tag": {
+ "$ref": "#/definitions/tagSelection",
+ "enum": [
+ "Wallet",
+ "Marketplace",
+ "Manufacturing",
+ "IoT",
+ "Financial Services",
+ "E-commerce",
+ "Business Services",
+ "Supply Chain",
+ "Real Estate",
+ "Healthcare",
+ "Tourism",
+ "Entertainments",
+ "RWA",
+ "Music",
+ "Tokenization"
+ ]
}
- },
- "required": [
- "type",
- "description"
- ]
+ }
},
- "minItems": 1,
- "maxItems": 3
- },
- "timeline": {
- "type": "object",
- "title": "Timeline",
- "properties": {
- "startDate": {
- "type": "string",
- "title": "Start Date",
- "format": "date"
- },
- "endDate": {
- "type": "string",
- "title": "End Date",
- "format": "date"
- },
- "durationInWeeks": {
- "type": "integer",
- "title": "Duration in Weeks",
- "minimum": 1,
- "maximum": 52
+ {
+ "properties": {
+ "group": {
+ "$ref": "#/definitions/tagGroup",
+ "const": "Events & Marketing"
+ },
+ "tag": {
+ "$ref": "#/definitions/tagSelection",
+ "enum": [
+ "Events",
+ "Marketing",
+ "Hackathons",
+ "Accelerator",
+ "Incubator"
+ ]
+ }
}
},
- "required": [
- "startDate",
- "endDate",
- "durationInWeeks"
- ]
- },
- "budget": {
- "type": "object",
- "title": "Milestone Budget",
- "properties": {
- "amount": {
- "type": "number",
- "title": "Amount in ADA",
- "minimum": 0
- },
- "breakdown": {
- "type": "array",
- "title": "Budget Breakdown",
- "items": {
- "type": "object",
- "properties": {
- "category": {
- "type": "string",
- "enum": [
- "Development",
- "Design",
- "Marketing",
- "Operations",
- "Other"
- ]
- },
- "amount": {
- "type": "number",
- "minimum": 0
- },
- "description": {
- "type": "string",
- "minLength": 10,
- "maxLength": 200,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- }
- },
- "required": [
- "category",
- "amount",
- "description"
+ {
+ "properties": {
+ "group": {
+ "$ref": "#/definitions/tagGroup",
+ "const": "Interoperability"
+ },
+ "tag": {
+ "$ref": "#/definitions/tagSelection",
+ "enum": [
+ "Cross-chain",
+ "Interoperability",
+ "Off-chain",
+ "Legal",
+ "Policy Advocacy",
+ "Standards"
]
+ }
+ }
+ },
+ {
+ "properties": {
+ "group": {
+ "$ref": "#/definitions/tagGroup",
+ "const": "Sustainability"
},
- "minItems": 1
+ "tag": {
+ "$ref": "#/definitions/tagSelection",
+ "enum": [
+ "Sustainability",
+ "Environment",
+ "Agriculture"
+ ]
+ }
}
},
- "required": [
- "amount",
- "breakdown"
- ]
- }
- },
- "required": [
- "title",
- "description",
- "deliverables",
- "acceptanceCriteria",
- "evidenceOfCompletion",
- "timeline",
- "budget"
- ]
- },
- "minItems": 3,
- "maxItems": 10
- }
- },
- "required": [
- "milestonesConfig",
- "milestonesList"
- ]
- },
- "finalPitch": {
- "type": "object",
- "title": "Final Pitch",
- "description": "Final project pitch including team, budget, and value proposition",
- "properties": {
- "team": {
- "type": "object",
- "title": "Team Information",
- "description": "Details about the project team and their capabilities",
- "properties": {
- "members": {
- "type": "array",
- "title": "Team Members",
- "description": "List of team members and their roles",
- "items": {
- "type": "object",
- "properties": {
- "name": {
- "type": "string",
- "title": "Name",
- "description": "Full name of the team member",
- "minLength": 2,
- "maxLength": 100,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- },
- "role": {
- "type": "string",
- "title": "Role",
- "description": "Primary role in the project",
- "minLength": 5,
- "maxLength": 100,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- },
- "expertise": {
- "type": "array",
- "title": "Areas of Expertise",
- "items": {
- "type": "string",
- "minLength": 3,
- "maxLength": 50,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
+ {
+ "properties": {
+ "group": {
+ "$ref": "#/definitions/tagGroup",
+ "const": "Smart Contracts"
},
- "minItems": 1,
- "maxItems": 5,
- "uniqueItems": true
- },
- "experience": {
- "type": "string",
- "title": "Relevant Experience",
- "description": "Brief description of relevant experience",
- "minLength": 50,
- "maxLength": 500,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- },
- "links": {
- "type": "array",
- "title": "Professional Links",
- "description": "Links to professional profiles or past work",
- "items": {
- "type": "object",
- "properties": {
- "type": {
- "type": "string",
- "enum": [
- "LinkedIn",
- "GitHub",
- "Portfolio",
- "Twitter",
- "Website",
- "Other"
- ]
- },
- "url": {
- "type": "string",
- "format": "uri",
- "pattern": "^https://",
- "pattern": "^https?://[\\w\\-]+(\\.[\\w\\-]+)+[/#?]?.*$",
- "contentMediaType": "text/uri-list"
- },
- "description": {
- "type": "string",
- "maxLength": 100,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- }
- },
- "required": [
- "type",
- "url"
+ "tag": {
+ "$ref": "#/definitions/tagSelection",
+ "enum": [
+ "Smart Contract",
+ "Smart Contracts",
+ "Audit",
+ "Oracles"
]
+ }
+ }
+ },
+ {
+ "properties": {
+ "group": {
+ "$ref": "#/definitions/tagGroup",
+ "const": "GameFi"
},
- "maxItems": 5
+ "tag": {
+ "$ref": "#/definitions/tagSelection",
+ "enum": [
+ "Gaming",
+ "Gaming (GameFi)",
+ "Entertainment",
+ "Metaverse"
+ ]
+ }
}
},
- "required": [
- "name",
- "role",
- "expertise",
- "experience"
- ]
- },
- "minItems": 1,
- "maxItems": 10
+ {
+ "properties": {
+ "group": {
+ "$ref": "#/definitions/tagGroup",
+ "const": "NFT"
+ },
+ "tag": {
+ "$ref": "#/definitions/tagSelection",
+ "enum": [
+ "NFT",
+ "CNFT",
+ "Collectibles",
+ "Digital Twin"
+ ]
+ }
+ }
+ }
+ ]
}
- },
- "required": [
- "members"
- ]
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/segment",
+ "title": "Your Project and Solution",
+ "properties": {
+ "solution": {
+ "$ref": "#/definitions/section",
+ "title": "Solution",
+ "description": "How you write this section will depend on what type of proposal you are writing. You might want to include details on:
- How do you perceive the problem you are solving?
- What are your reasons for approaching it in the way that you have?
- Who will your project engage?
- How will you demonstrate or prove your impact?
Explain what is unique about your solution, who will benefit, and why this is important to Cardano.
",
+ "properties": {
+ "solution": {
+ "$ref": "#/definitions/multiLineTextEntryMarkdown",
+ "minLength": 1,
+ "maxLength": 10240,
+ "examples": [
+ "Our solution involves developing a decentralized education platform that will..."
+ ]
+ }
+ }
},
- "budget": {
- "type": "object",
- "title": "Budget Details",
- "description": "Detailed budget breakdown and justification",
+ "impact": {
+ "$ref": "#/definitions/section",
+ "title": "Impact",
+ "description": "Please include here a description of how you intend to measure impact (whether quantitative or qualitative) and how and with whom you will share your outputs:
- In what way will the success of your project bring value to the Cardano Community?
- How will you measure this impact?
- How will you share the outputs and opportunities that result from your project?
",
"properties": {
- "totalBudget": {
- "type": "number",
- "title": "Total Budget (ADA)",
- "description": "Total amount requested in ADA",
- "minimum": 0,
- "maximum": 1000000
- },
- "categories": {
- "type": "array",
- "title": "Budget Categories",
- "description": "Breakdown of budget by category",
- "items": {
- "type": "object",
- "properties": {
- "category": {
- "type": "string",
- "enum": [
- "Development",
- "Design",
- "Marketing",
- "Operations",
- "Research",
- "Community Management",
- "Legal",
- "Other"
- ]
- },
- "amount": {
- "type": "number",
- "minimum": 0
- },
- "description": {
- "type": "string",
- "minLength": 20,
- "maxLength": 300,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- }
- },
- "required": [
- "category",
- "amount",
- "description"
- ]
- },
- "minItems": 1
+ "impact": {
+ "$ref": "#/definitions/multiLineTextEntryMarkdown",
+ "minLength": 1,
+ "maxLength": 10240
}
- },
- "required": [
- "totalBudget",
- "categories"
- ]
+ }
},
- "valueProposition": {
- "type": "object",
- "title": "Value Proposition",
- "description": "Justification of the project's value for money",
+ "feasibility": {
+ "$ref": "#/definitions/section",
+ "title": "Capabilities & Feasibility",
+ "description": "Please describe your existing capabilities that demonstrate how and why you believe you’re best suited to deliver this project?
Please include the steps or processes that demonstrate that you can be trusted to manage funds properly.
",
"properties": {
- "costBenefitAnalysis": {
- "type": "string",
- "title": "Cost-Benefit Analysis",
- "description": "Analysis of the project's costs versus its benefits to the Cardano ecosystem",
- "minLength": 100,
- "maxLength": 1000,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- },
- "longTermValue": {
- "type": "string",
- "title": "Long-term Value",
- "description": "Description of the long-term value and sustainability of the project",
- "minLength": 100,
- "maxLength": 1000,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- },
- "communityBenefits": {
- "type": "array",
- "title": "Community Benefits",
- "description": "Specific benefits to the Cardano community",
- "items": {
- "type": "string",
- "minLength": 20,
- "maxLength": 200,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- },
- "minItems": 2,
- "maxItems": 5
+ "feasibility": {
+ "$ref": "#/definitions/multiLineTextEntryMarkdown",
+ "minLength": 1,
+ "maxLength": 10240
}
- },
- "required": [
- "costBenefitAnalysis",
- "longTermValue",
- "communityBenefits"
- ]
+ }
}
- },
- "required": [
- "team",
- "budget",
- "valueProposition"
- ]
+ }
},
- "mandatoryAcknowledgments": {
- "type": "object",
- "title": "Mandatory Acknowledgments",
- "description": "Required acknowledgments and agreements for proposal submission",
+ "milestones": {
+ "$ref": "#/definitions/segment",
+ "title": "Milestones",
"properties": {
- "fundRules": {
- "type": "object",
- "title": "Fund Rules Agreement",
+ "milestones": {
+ "$ref": "#/definitions/section",
+ "description": "A clear set of milestones and acceptance criteria will demonstrate your capability to deliver the project as proposed. More guidance on submitting milestones as part of your project proposal can be found here.
Milestones guidance
- For Grant Amounts of up to 75k ada, at least 2 milestones, plus the final one including Project Close-out Report and Video, must be included (3 milestones in total)
- For Grant Amounts over 75k ada up to 150k ada, at least 3 milestones, plus the final one including Project Close-out Report and Video, must be included (4 milestones in total)
- For Grant Amounts over 150k ada up to 300k ada, at least 4 milestones, plus the final one including Project Close-out Report and Video, must be included (5 milestones in total)
- For Grant Amounts exceeding 300k ada, at least 5 milestones, plus the final one including Project Close-out Report and Video, must be included (6 milestones in total)
",
"properties": {
- "acknowledgment": {
- "type": "boolean",
- "title": "Fund Rules Acknowledgment",
- "description": "I confirm that I have read and agree to be bound by the Fund Rules",
- "const": true
- },
- "version": {
- "type": "string",
- "title": "Fund Rules Version",
- "description": "Version of the Fund Rules being acknowledged",
- "pattern": "^F[0-9]{1,3}$",
- "examples": [
- "F14",
- "F15"
- ]
- },
- "timestamp": {
- "type": "string",
- "title": "Acknowledgment Timestamp",
- "description": "When the rules were acknowledged",
- "format": "date-time",
- "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]+)?(Z|[+-][0-9]{2}:[0-9]{2})$",
- "examples": [
- "2024-01-20T15:30:00Z"
- ]
+ "declared": {
+ "$ref": "#/definitions/multiLineTextEntryListMarkdown",
+ "minItems": 3,
+ "maxItems": 6
}
- },
- "required": [
- "acknowledgment",
- "version",
- "timestamp"
- ]
- },
- "termsAndConditions": {
- "type": "object",
- "title": "Terms and Conditions Agreement",
+ }
+ }
+ }
+ },
+ "pitch": {
+ "$ref": "#/definitions/segment",
+ "title": "Final Pitch",
+ "properties": {
+ "team": {
+ "$ref": "#/definitions/section",
+ "title": "Team",
"properties": {
- "acknowledgment": {
- "type": "boolean",
- "title": "Terms and Conditions Acknowledgment",
- "description": "I confirm that I have read and agree to be bound by the Project Catalyst Terms and Conditions",
- "const": true
- },
- "version": {
- "type": "string",
- "title": "Terms Version",
- "description": "Version of the Terms and Conditions being acknowledged",
- "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$",
- "examples": [
- "1.0.0",
- "2.1.3"
- ]
- },
- "documentUrl": {
- "type": "string",
- "title": "Terms Document URL",
- "description": "URL to the specific version of terms and conditions",
- "format": "uri",
- "pattern": "^https://[\\w\\-\\.]+\\.[a-zA-Z]{2,}/.*$",
- "contentMediaType": "text/html"
- },
- "timestamp": {
- "type": "string",
- "title": "Acknowledgment Timestamp",
- "description": "When the terms were acknowledged",
- "format": "date-time",
- "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]+)?(Z|[+-][0-9]{2}:[0-9]{2})$",
- "examples": [
- "2024-01-20T15:30:00Z"
- ]
+ "who": {
+ "$ref": "#/definitions/multiLineTextEntryMarkdown",
+ "title": "Who is in the project team and what are their roles?",
+ "description": "p>List your team, their Linkedin profiles (or similar) and state what aspect of the proposal’s work each team member will undertake.
If you are planning to recruit additional team members, please state what specific skills you will be looking for in the people you recruit, so readers can see that you understand what skills will be needed to complete the project.
You are expected to have already engaged the relevant members of the organizations referenced so you understand if they are willing and/or have capacity to support the project. If you have not taken any steps to engage with your team yet, it is likely that the resources will not be available if you are approved for funding, which can jeopardize the project before it has even begun. The Catalyst team cannot help with this, meaning you are expected to have understood the requirements and engaged the necessary people before submitting a proposal.
Have you engaged anyone on any of the technical group channels (eg Discord or Telegram), or do you have a direct line of communications with the people and resources required?
Important: Catalyst funding is not anonymous, and some level of ‘proof of life’ verifications will take place before initial funding is released. Also remember that your proposal will be publicly available, so make sure to obtain any consent required before including confidential or third party information.
All Project Participants must disclose their role and scope of services across any submitted proposals, even if they are not in the lead or co-proposer role, such as an implementer, vendor, service provider, etc. Failure to disclose this information may lead to disqualification from the current grant round.
",
+ "minLength": 1,
+ "maxLength": 10240
}
- },
- "required": [
- "acknowledgment",
- "version",
- "timestamp",
- "documentUrl"
- ]
+ }
},
- "privacyPolicy": {
- "type": "object",
- "title": "Privacy Policy Agreement",
+ "budget": {
+ "$ref": "#/definitions/section",
+ "title": "Budget & Costs",
"properties": {
- "acknowledgment": {
- "type": "boolean",
- "title": "Privacy Policy Acknowledgment",
- "description": "I acknowledge and agree that any data I share will be processed in accordance with the Catalyst FCS Privacy Policy",
- "const": true
- },
- "version": {
- "type": "string",
- "title": "Privacy Policy Version",
- "description": "Version of the Privacy Policy being acknowledged",
- "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$",
- "examples": [
- "1.0.0",
- "2.1.3"
- ]
- },
- "documentUrl": {
- "type": "string",
- "title": "Privacy Policy URL",
- "description": "URL to the specific version of privacy policy",
- "format": "uri",
- "pattern": "^https://[\\w\\-\\.]+\\.[a-zA-Z]{2,}/.*$",
- "contentMediaType": "text/html"
- },
- "timestamp": {
- "type": "string",
- "title": "Acknowledgment Timestamp",
- "description": "When the privacy policy was acknowledged",
- "format": "date-time",
- "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]+)?(Z|[+-][0-9]{2}:[0-9]{2})$",
- "examples": [
- "2024-01-20T15:30:00Z"
- ]
+ "costs": {
+ "$ref": "#/definitions/multiLineTextEntryMarkdown",
+ "title": "Please provide a cost breakdown of the proposed work and resources",
+ "description": "Make sure every element mentioned in your plan reflects its cost. It may be helpful to refer to your plan and timeline, list all the resources you will need at each stage, and what they cost.
Here, provide a clear description of any third party product or service you will be using. This could be hardware, software licenses, professional services (legal, accounting, code auditing, etc) but does not need to include the use of contracted programmers and developers.
The exact budget elements you include will depend on what type of work you are doing, and you might need to give less detail for a small, low-budget proposal. If the cost of the project will exceed the funding request, please provide information about alternative sources of funding.
Consider including budget elements for publicity / marketing / promotion / community engagement; project management; documentation; and reporting back to the community. Most proposals need these, but many proposers forget to include them.
It is the project team’s responsibility to properly manage the funds provided. Make sure to reference Fund Rules to understand eligibility around costs.
",
+ "minLength": 1,
+ "maxLength": 10240
}
- },
- "required": [
- "acknowledgment",
- "version",
- "timestamp",
- "documentUrl"
- ]
+ }
},
- "intellectualProperty": {
- "type": "object",
- "title": "Intellectual Property Declaration",
+ "value": {
+ "$ref": "#/definitions/section",
+ "title": "Value for Money",
"properties": {
- "acknowledgment": {
- "type": "boolean",
- "title": "IP Rights Acknowledgment",
- "description": "I confirm that I have the necessary rights to all intellectual property included in this proposal",
- "const": true
- },
- "details": {
- "type": "string",
- "title": "IP Details",
- "description": "Additional details about intellectual property rights (if applicable)",
- "maxLength": 1000,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- },
- "attachments": {
- "type": "array",
- "title": "IP Documentation",
- "description": "Supporting documentation for IP rights (if applicable)",
- "items": {
- "type": "object",
- "properties": {
- "documentType": {
- "type": "string",
- "enum": [
- "patent",
- "trademark",
- "copyright",
- "license",
- "other"
- ],
- "description": "Type of IP documentation"
- },
- "documentUrl": {
- "type": "string",
- "format": "uri",
- "pattern": "^https://[\\w\\-\\.]+\\.[a-zA-Z]{2,}/.*$",
- "contentMediaType": "application/pdf"
- },
- "description": {
- "type": "string",
- "maxLength": 500,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- }
- },
- "required": [
- "documentType",
- "documentUrl",
- "description"
- ]
- },
- "maxItems": 10
- },
- "timestamp": {
- "type": "string",
- "title": "Acknowledgment Timestamp",
- "description": "When the IP declaration was made",
- "format": "date-time",
- "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]+)?(Z|[+-][0-9]{2}:[0-9]{2})$",
- "examples": [
- "2024-01-20T15:30:00Z"
- ]
+ "note": {
+ "$ref": "#/definitions/multiLineTextEntryMarkdown",
+ "title": "How does the cost of the project represent value for money for the Cardano ecosystem?",
+ "description": "Use the response to provide the context about the costs you listed previously, particularly if they are high.
It may be helpful to include some brief information on how you have decided on the costs of the project.
For instance, can you justify with supporting evidence that costs are proportional to the average wage in your country, or typical freelance rates in your industry? Is there anything else that helps to support how the project represents value for money?
",
+ "minLength": 1,
+ "maxLength": 10240
}
- },
- "required": [
- "acknowledgment",
- "timestamp"
- ]
- },
- "compliance": {
- "type": "object",
- "title": "Compliance Declaration",
+ }
+ }
+ }
+ },
+ "agreements": {
+ "$ref": "#/definitions/segment",
+ "title": "Acknowledgements",
+ "properties": {
+ "mandatory": {
+ "$ref": "#/definitions/section",
+ "title": "Mandatory",
"properties": {
- "legalCompliance": {
- "type": "boolean",
- "title": "Legal Compliance",
- "description": "I confirm that my proposal complies with all applicable laws and regulations",
- "const": true
- },
- "noConflictOfInterest": {
- "type": "boolean",
- "title": "No Conflict of Interest",
- "description": "I confirm that there are no undisclosed conflicts of interest",
- "const": true
- },
- "accurateInformation": {
- "type": "boolean",
- "title": "Information Accuracy",
- "description": "I confirm that all information provided is accurate and complete",
- "const": true
- },
- "jurisdictions": {
- "type": "array",
- "title": "Applicable Jurisdictions",
- "description": "List of jurisdictions where compliance is declared",
- "items": {
- "type": "string",
- "pattern": "^[A-Z]{2}$",
- "description": "ISO 3166-1 alpha-2 country code"
- },
- "minItems": 1,
- "uniqueItems": true
- },
- "timestamp": {
- "type": "string",
- "title": "Acknowledgment Timestamp",
- "description": "When the compliance declaration was made",
- "format": "date-time",
- "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]+)?(Z|[+-][0-9]{2}:[0-9]{2})$",
- "examples": [
- "2024-01-20T15:30:00Z"
- ]
+ "fund_rules": {
+ "$ref": "#/definitions/agreementConfirmation",
+ "title": "Fund Rules:",
+ "description": "By submitting a proposal to Project Catalyst Fund14, I confirm that I have read and agree to be bound by the Fund Rules.
"
+ },
+ "terms_and_conditions": {
+ "$ref": "#/definitions/agreementConfirmation",
+ "title": "Terms and Conditions:",
+ "description": "By submitting a proposal to Project Catalyst Fund14, I confirm that I have read and agree to be bound by the Project Catalyst Terms and Conditions.
"
+ },
+ "privacy_policy": {
+ "$ref": "#/definitions/agreementConfirmation",
+ "title": "Privacy Policy: ",
+ "description": "I acknowledge and agree that any data I share in connection with my participation in Project Catalyst Fund14 will be collected, stored, used and processed in accordance with the Catalyst FC’s Privacy Policy.
"
}
},
"required": [
- "legalCompliance",
- "noConflictOfInterest",
- "accurateInformation",
- "jurisdictions",
- "timestamp"
+ "fund_rules",
+ "terms_and_conditions",
+ "privacy_policy"
+ ],
+ "x-order": [
+ "fund_rules",
+ "terms_and_conditions",
+ "privacy_policy"
]
- },
- "additionalAcknowledgments": {
- "type": "array",
- "title": "Additional Acknowledgments",
- "description": "Any additional acknowledgments required for specific proposal types",
- "items": {
- "type": "object",
- "properties": {
- "type": {
- "type": "string",
- "title": "Acknowledgment Type",
- "minLength": 5,
- "maxLength": 100,
- "pattern": "^[a-zA-Z][a-zA-Z0-9_\\-\\.]*$"
- },
- "acknowledgment": {
- "type": "boolean",
- "title": "Acknowledgment",
- "const": true
- },
- "description": {
- "type": "string",
- "title": "Description",
- "description": "Detailed description of what is being acknowledged",
- "minLength": 10,
- "maxLength": 500,
- "pattern": "^[\\S\\s]*$",
- "contentMediaType": "text/plain"
- },
- "documentUrl": {
- "type": "string",
- "title": "Reference Document",
- "description": "URL to the document being acknowledged",
- "format": "uri",
- "pattern": "^https://[\\w\\-\\.]+\\.[a-zA-Z]{2,}/.*$",
- "contentMediaType": "text/html"
- },
- "timestamp": {
- "type": "string",
- "title": "Acknowledgment Timestamp",
- "format": "date-time",
- "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]+)?(Z|[+-][0-9]{2}:[0-9]{2})$",
- "examples": [
- "2024-01-20T15:30:00Z"
- ]
- }
- },
- "required": [
- "type",
- "acknowledgment",
- "description",
- "timestamp"
- ]
- }
}
},
- "required": [
- "fundRules",
- "termsAndConditions",
- "privacyPolicy",
- "intellectualProperty",
- "compliance"
+ "x-order": [
+ "mandatory"
]
}
- }
+ },
+ "x-order": [
+ "setup",
+ "summary",
+ "horizons",
+ "details",
+ "milestones",
+ "pitch",
+ "agreement"
+ ]
}
\ No newline at end of file
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/example.proposal.json b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/example.proposal.json
index d524fec31ae..4b2d77cdbc3 100644
--- a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/example.proposal.json
+++ b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/example.proposal.json
@@ -24,7 +24,11 @@
},
"problem": {
"statement": "Current challenge in the Cardano ecosystem...",
- "impact": ["Technical Infrastructure", "Developer Tooling", "Adoption"]
+ "impact": [
+ "Technical Infrastructure",
+ "Developer Tooling",
+ "Adoption"
+ ]
},
"solution": {
"summary": "Our solution provides a comprehensive toolkit...",
@@ -51,7 +55,11 @@
"primaryCategory": "Development & Tools",
"subCategory": "Developer Tools"
},
- "tags": ["defi", "developer-tools", "infrastructure"],
+ "tags": [
+ "defi",
+ "developer-tools",
+ "infrastructure"
+ ],
"impact": {
"timeframe": "Medium-term (6-18 months)",
"scale": "Global",
@@ -68,7 +76,10 @@
"solution": {
"description": "Our solution provides a comprehensive toolkit...",
"uniqueValue": "First integrated testing framework for Cardano",
- "targetAudience": ["Cardano Developers", "DApp Teams"],
+ "targetAudience": [
+ "Cardano Developers",
+ "DApp Teams"
+ ],
"implementation": "We will use an agile development approach..."
},
"impact": {
@@ -94,6 +105,18 @@
}
},
"milestones": {
+ "milestones": {
+ "declared": [
+ "a",
+ "bb",
+ "cccccccccccccccccccccccc",
+ "dd",
+ "eee",
+ "fff"
+ ]
+ }
+ },
+ "milestonez": {
"milestonesConfig": {
"grantAmount": 150000,
"numberOfMilestones": 4
@@ -143,7 +166,10 @@
{
"name": "John Doe",
"role": "Project Lead",
- "expertise": ["Blockchain Development", "Smart Contracts"],
+ "expertise": [
+ "Blockchain Development",
+ "Smart Contracts"
+ ],
"experience": "10 years in software development",
"links": [
{
@@ -200,7 +226,10 @@
"legalCompliance": true,
"noConflictOfInterest": true,
"accurateInformation": true,
- "jurisdictions": ["US", "GB"],
+ "jurisdictions": [
+ "US",
+ "GB"
+ ],
"timestamp": "2024-01-20T15:30:00Z"
}
}
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/extra-definitions.txt b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/extra-definitions.txt
new file mode 100644
index 00000000000..8278ccf1d2f
--- /dev/null
+++ b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/extra-definitions.txt
@@ -0,0 +1,1079 @@
+Not in the F13 proposal, or the F14 base document?
+
+
+ "proposalDetails": {
+ "type": "object",
+ "title": "Proposal Details",
+ "description": "Detailed information about your proposal's solution, impact, and feasibility",
+ "properties": {
+ "solution": {
+ "type": "object",
+ "title": "Solution Description",
+ "description": "Detailed description of your proposed solution",
+ "x-guidance": "YOUR PROJECT AND SOLUTION
How you write this section will depend on what type of proposal you are writing. You might want to include details on:
- How do you perceive the problem you are solving?
- What are your reasons for approaching it in the way that you have?
- Who will your project engage?
- How will you demonstrate or prove your impact?
Explain what is unique about your solution, who will benefit, and why this is important to Cardano.
",
+ "properties": {
+ "description": {
+ "type": "string",
+ "title": "Solution Description",
+ "description": "Provide a comprehensive description of your proposed solution",
+ "minLength": 100,
+ "maxLength": 2000,
+ "examples": [
+ "Our solution involves developing a decentralized education platform that will..."
+ ],
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
+ },
+ "uniqueValue": {
+ "type": "string",
+ "title": "Unique Value Proposition",
+ "description": "What makes your solution unique and innovative?",
+ "minLength": 50,
+ "maxLength": 500,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
+ },
+ "targetAudience": {
+ "type": "array",
+ "title": "Target Audience",
+ "description": "Who will benefit from your solution?",
+ "items": {
+ "type": "string",
+ "minLength": 5,
+ "maxLength": 100,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
+ },
+ "minItems": 1,
+ "maxItems": 5,
+ "uniqueItems": true
+ },
+ "implementation": {
+ "type": "string",
+ "title": "Implementation Approach",
+ "description": "How will you implement your solution?",
+ "minLength": 100,
+ "maxLength": 1000,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
+ }
+ },
+ "required": [
+ "description",
+ "uniqueValue",
+ "targetAudience",
+ "implementation"
+ ]
+ },
+ "impact": {
+ "type": "object",
+ "title": "Project Impact",
+ "description": "Define and measure the impact of your project",
+ "x-guidance": "Please include here a description of how you intend to measure impact (whether quantitative or qualitative) and how and with whom you will share your outputs:
- In what way will the success of your project bring value to the Cardano Community?
- How will you measure this impact?
- How will you share the outputs and opportunities that result from your project?
",
+ "properties": {
+ "communityBenefit": {
+ "type": "string",
+ "title": "Community Benefit",
+ "description": "How will the Cardano community benefit from your project?",
+ "minLength": 100,
+ "maxLength": 1000,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
+ },
+ "metrics": {
+ "type": "array",
+ "title": "Impact Metrics",
+ "description": "Specific metrics to measure project success",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "title": "Metric Name",
+ "minLength": 5,
+ "maxLength": 100,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
+ },
+ "description": {
+ "type": "string",
+ "title": "Metric Description",
+ "minLength": 20,
+ "maxLength": 300,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
+ },
+ "target": {
+ "type": "string",
+ "title": "Target Value",
+ "minLength": 1,
+ "maxLength": 100,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
+ },
+ "measurement": {
+ "type": "string",
+ "title": "Measurement Method",
+ "minLength": 20,
+ "maxLength": 300,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
+ }
+ },
+ "required": [
+ "name",
+ "description",
+ "target",
+ "measurement"
+ ]
+ },
+ "minItems": 2,
+ "maxItems": 5
+ },
+ "outputs": {
+ "type": "array",
+ "title": "Project Outputs",
+ "description": "Tangible outputs and deliverables from the project",
+ "items": {
+ "type": "string",
+ "minLength": 10,
+ "maxLength": 200,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
+ },
+ "minItems": 1,
+ "maxItems": 10,
+ "uniqueItems": true
+ }
+ },
+ "required": [
+ "communityBenefit",
+ "metrics",
+ "outputs"
+ ]
+ },
+ "capability": {
+ "type": "object",
+ "title": "Capability & Feasibility",
+ "description": "Demonstrate your ability to deliver the project successfully",
+ "x-guidance": "Please describe your existing capabilities that demonstrate how and why you believe you're best suited to deliver this project? Please include the steps or processes that demonstrate that you can be trusted to manage funds properly.
",
+ "properties": {
+ "teamExperience": {
+ "type": "string",
+ "title": "Team Experience",
+ "description": "Describe your team's relevant experience and capabilities",
+ "minLength": 100,
+ "maxLength": 1000,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
+ },
+ "feasibilityApproach": {
+ "type": "string",
+ "title": "Feasibility Approach",
+ "description": "How will you validate the feasibility of your approach?",
+ "minLength": 100,
+ "maxLength": 1000,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
+ },
+ "fundManagement": {
+ "type": "string",
+ "title": "Fund Management",
+ "description": "How will you ensure proper management and accountability of funds?",
+ "minLength": 100,
+ "maxLength": 1000,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
+ }
+ },
+ "required": [
+ "teamExperience",
+ "feasibilityApproach",
+ "fundManagement"
+ ]
+ }
+ },
+ "required": [
+ "solution",
+ "impact",
+ "capability"
+ ]
+},
+"milestones": {
+ "type": "object",
+ "title": "Project Milestones",
+ "description": "Detailed project milestones and deliverables",
+ "x-guidance": "A clear set of milestones and acceptance criteria will demonstrate your capability to deliver the project as proposed. More guidance on submitting milestones as part of your project proposal can be found here
For Grant Amounts of up to 75k ada, at least 2 milestones, plus the final one including Project Close-out Report and Video, must be included (3 milestones in total)
For Grant Amounts over 75k ada up to 150k ada, at least 3 milestones, plus the final one including Project Close-out Report and Video, must be included (4 milestones in total)
For Grant Amounts over 150k ada up to 300k ada, at least 4 milestones, plus the final one including Project Close-out Report and Video, must be included (5 milestones in total)
For Grant Amounts exceeding 300k ada, at least 5 milestones, plus the final one including Project Close-out Report and Video, must be included (6 milestones in total)
",
+ "properties": {
+ "milestonesConfig": {
+ "type": "object",
+ "title": "Milestones Configuration",
+ "description": "Configuration for number of milestones",
+ "properties": {
+ "grantAmount": {
+ "type": "number",
+ "title": "Grant Amount in ADA",
+ "description": "Total grant amount requested in ADA",
+ "minimum": 0,
+ "maximum": 1000000
+ },
+ "numberOfMilestones": {
+ "type": "integer",
+ "title": "Number of Milestones",
+ "description": "Total number of milestones including the final milestone",
+ "minimum": 2,
+ "maximum": 6
+ }
+ },
+ "required": [
+ "grantAmount",
+ "numberOfMilestones"
+ ]
+ },
+ "milestonesList": {
+ "type": "array",
+ "title": "List of Milestones",
+ "description": "Detailed description of each project milestone",
+ "items": {
+ "type": "object",
+ "title": "Milestone",
+ "properties": {
+ "title": {
+ "type": "string",
+ "title": "Milestone Title",
+ "description": "Short, descriptive title for the milestone",
+ "minLength": 5,
+ "maxLength": 100,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
+ },
+ "description": {
+ "type": "string",
+ "title": "Milestone Description",
+ "description": "Detailed description of what this milestone entails",
+ "minLength": 50,
+ "maxLength": 1000,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
+ },
+ "deliverables": {
+ "type": "array",
+ "title": "Deliverables",
+ "description": "Specific outputs and deliverables for this milestone",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "title": "Deliverable Name",
+ "minLength": 5,
+ "maxLength": 100,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
+ },
+ "description": {
+ "type": "string",
+ "title": "Deliverable Description",
+ "minLength": 20,
+ "maxLength": 500,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
+ },
+ "type": {
+ "type": "string",
+ "enum": [
+ "Documentation",
+ "Software",
+ "Report",
+ "Presentation",
+ "Video",
+ "Other"
+ ]
+ }
+ },
+ "required": [
+ "name",
+ "description",
+ "type"
+ ]
+ },
+ "minItems": 1,
+ "maxItems": 5
+ },
+ "acceptanceCriteria": {
+ "type": "array",
+ "title": "Acceptance Criteria",
+ "description": "Specific criteria that must be met to consider this milestone complete",
+ "items": {
+ "type": "string",
+ "minLength": 10,
+ "maxLength": 200,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
+ },
+ "minItems": 1,
+ "maxItems": 5
+ },
+ "evidenceOfCompletion": {
+ "type": "array",
+ "title": "Evidence of Completion",
+ "description": "How will you demonstrate that this milestone is complete?",
+ "items": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "title": "Evidence Type",
+ "enum": [
+ "Code Repository",
+ "Documentation",
+ "Demo Video",
+ "Test Results",
+ "Metrics Report",
+ "User Feedback",
+ "Other"
+ ]
+ },
+ "description": {
+ "type": "string",
+ "title": "Evidence Description",
+ "minLength": 20,
+ "maxLength": 300,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
+ }
+ },
+ "required": [
+ "type",
+ "description"
+ ]
+ },
+ "minItems": 1,
+ "maxItems": 3
+ },
+ "timeline": {
+ "type": "object",
+ "title": "Timeline",
+ "properties": {
+ "startDate": {
+ "type": "string",
+ "title": "Start Date",
+ "format": "date"
+ },
+ "endDate": {
+ "type": "string",
+ "title": "End Date",
+ "format": "date"
+ },
+ "durationInWeeks": {
+ "type": "integer",
+ "title": "Duration in Weeks",
+ "minimum": 1,
+ "maximum": 52
+ }
+ },
+ "required": [
+ "startDate",
+ "endDate",
+ "durationInWeeks"
+ ]
+ },
+ "budget": {
+ "type": "object",
+ "title": "Milestone Budget",
+ "properties": {
+ "amount": {
+ "type": "number",
+ "title": "Amount in ADA",
+ "minimum": 0
+ },
+ "breakdown": {
+ "type": "array",
+ "title": "Budget Breakdown",
+ "items": {
+ "type": "object",
+ "properties": {
+ "category": {
+ "type": "string",
+ "enum": [
+ "Development",
+ "Design",
+ "Marketing",
+ "Operations",
+ "Other"
+ ]
+ },
+ "amount": {
+ "type": "number",
+ "minimum": 0
+ },
+ "description": {
+ "type": "string",
+ "minLength": 10,
+ "maxLength": 200,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
+ }
+ },
+ "required": [
+ "category",
+ "amount",
+ "description"
+ ]
+ },
+ "minItems": 1
+ }
+ },
+ "required": [
+ "amount",
+ "breakdown"
+ ]
+ }
+ },
+ "required": [
+ "title",
+ "description",
+ "deliverables",
+ "acceptanceCriteria",
+ "evidenceOfCompletion",
+ "timeline",
+ "budget"
+ ]
+ },
+ "minItems": 3,
+ "maxItems": 10
+ }
+ },
+ "required": [
+ "milestonesConfig",
+ "milestonesList"
+ ]
+},
+"finalPitch": {
+ "type": "object",
+ "title": "Final Pitch",
+ "description": "Final project pitch including team, budget, and value proposition",
+ "properties": {
+ "team": {
+ "type": "object",
+ "title": "Team Information",
+ "description": "Details about the project team and their capabilities",
+ "properties": {
+ "members": {
+ "type": "array",
+ "title": "Team Members",
+ "description": "List of team members and their roles",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "title": "Name",
+ "description": "Full name of the team member",
+ "minLength": 2,
+ "maxLength": 100,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
+ },
+ "role": {
+ "type": "string",
+ "title": "Role",
+ "description": "Primary role in the project",
+ "minLength": 5,
+ "maxLength": 100,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
+ },
+ "expertise": {
+ "type": "array",
+ "title": "Areas of Expertise",
+ "items": {
+ "type": "string",
+ "minLength": 3,
+ "maxLength": 50,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
+ },
+ "minItems": 1,
+ "maxItems": 5,
+ "uniqueItems": true
+ },
+ "experience": {
+ "type": "string",
+ "title": "Relevant Experience",
+ "description": "Brief description of relevant experience",
+ "minLength": 50,
+ "maxLength": 500,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
+ },
+ "links": {
+ "type": "array",
+ "title": "Professional Links",
+ "description": "Links to professional profiles or past work",
+ "items": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "LinkedIn",
+ "GitHub",
+ "Portfolio",
+ "Twitter",
+ "Website",
+ "Other"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https://",
+ "pattern": "^https?://[\\w\\-]+(\\.[\\w\\-]+)+[/#?]?.*$",
+ "contentMediaType": "text/uri-list"
+ },
+ "description": {
+ "type": "string",
+ "maxLength": 100,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
+ }
+ },
+ "required": [
+ "type",
+ "url"
+ ]
+ },
+ "maxItems": 5
+ }
+ },
+ "required": [
+ "name",
+ "role",
+ "expertise",
+ "experience"
+ ]
+ },
+ "minItems": 1,
+ "maxItems": 10
+ }
+ },
+ "required": [
+ "members"
+ ]
+ },
+ "budget": {
+ "type": "object",
+ "title": "Budget Details",
+ "description": "Detailed budget breakdown and justification",
+ "properties": {
+ "totalBudget": {
+ "type": "number",
+ "title": "Total Budget (ADA)",
+ "description": "Total amount requested in ADA",
+ "minimum": 0,
+ "maximum": 1000000
+ },
+ "categories": {
+ "type": "array",
+ "title": "Budget Categories",
+ "description": "Breakdown of budget by category",
+ "items": {
+ "type": "object",
+ "properties": {
+ "category": {
+ "type": "string",
+ "enum": [
+ "Development",
+ "Design",
+ "Marketing",
+ "Operations",
+ "Research",
+ "Community Management",
+ "Legal",
+ "Other"
+ ]
+ },
+ "amount": {
+ "type": "number",
+ "minimum": 0
+ },
+ "description": {
+ "type": "string",
+ "minLength": 20,
+ "maxLength": 300,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
+ }
+ },
+ "required": [
+ "category",
+ "amount",
+ "description"
+ ]
+ },
+ "minItems": 1
+ }
+ },
+ "required": [
+ "totalBudget",
+ "categories"
+ ]
+ },
+ "valueProposition": {
+ "type": "object",
+ "title": "Value Proposition",
+ "description": "Justification of the project's value for money",
+ "properties": {
+ "costBenefitAnalysis": {
+ "type": "string",
+ "title": "Cost-Benefit Analysis",
+ "description": "Analysis of the project's costs versus its benefits to the Cardano ecosystem",
+ "minLength": 100,
+ "maxLength": 1000,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
+ },
+ "longTermValue": {
+ "type": "string",
+ "title": "Long-term Value",
+ "description": "Description of the long-term value and sustainability of the project",
+ "minLength": 100,
+ "maxLength": 1000,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
+ },
+ "communityBenefits": {
+ "type": "array",
+ "title": "Community Benefits",
+ "description": "Specific benefits to the Cardano community",
+ "items": {
+ "type": "string",
+ "minLength": 20,
+ "maxLength": 200,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
+ },
+ "minItems": 2,
+ "maxItems": 5
+ }
+ },
+ "required": [
+ "costBenefitAnalysis",
+ "longTermValue",
+ "communityBenefits"
+ ]
+ }
+ },
+ "required": [
+ "team",
+ "budget",
+ "valueProposition"
+ ]
+},
+"mandatoryAcknowledgments": {
+ "type": "object",
+ "title": "Mandatory Acknowledgments",
+ "description": "Required acknowledgments and agreements for proposal submission",
+ "properties": {
+ "fundRules": {
+ "type": "object",
+ "title": "Fund Rules Agreement",
+ "properties": {
+ "acknowledgment": {
+ "type": "boolean",
+ "title": "Fund Rules Acknowledgment",
+ "description": "I confirm that I have read and agree to be bound by the Fund Rules",
+ "const": true
+ },
+ "version": {
+ "type": "string",
+ "title": "Fund Rules Version",
+ "description": "Version of the Fund Rules being acknowledged",
+ "pattern": "^F[0-9]{1,3}$",
+ "examples": [
+ "F14",
+ "F15"
+ ]
+ },
+ "timestamp": {
+ "type": "string",
+ "title": "Acknowledgment Timestamp",
+ "description": "When the rules were acknowledged",
+ "format": "date-time",
+ "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]+)?(Z|[+-][0-9]{2}:[0-9]{2})$",
+ "examples": [
+ "2024-01-20T15:30:00Z"
+ ]
+ }
+ },
+ "required": [
+ "acknowledgment",
+ "version",
+ "timestamp"
+ ]
+ },
+ "termsAndConditions": {
+ "type": "object",
+ "title": "Terms and Conditions Agreement",
+ "properties": {
+ "acknowledgment": {
+ "type": "boolean",
+ "title": "Terms and Conditions Acknowledgment",
+ "description": "I confirm that I have read and agree to be bound by the Project Catalyst Terms and Conditions",
+ "const": true
+ },
+ "version": {
+ "type": "string",
+ "title": "Terms Version",
+ "description": "Version of the Terms and Conditions being acknowledged",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$",
+ "examples": [
+ "1.0.0",
+ "2.1.3"
+ ]
+ },
+ "documentUrl": {
+ "type": "string",
+ "title": "Terms Document URL",
+ "description": "URL to the specific version of terms and conditions",
+ "format": "uri",
+ "pattern": "^https://[\\w\\-\\.]+\\.[a-zA-Z]{2,}/.*$",
+ "contentMediaType": "text/html"
+ },
+ "timestamp": {
+ "type": "string",
+ "title": "Acknowledgment Timestamp",
+ "description": "When the terms were acknowledged",
+ "format": "date-time",
+ "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]+)?(Z|[+-][0-9]{2}:[0-9]{2})$",
+ "examples": [
+ "2024-01-20T15:30:00Z"
+ ]
+ }
+ },
+ "required": [
+ "acknowledgment",
+ "version",
+ "timestamp",
+ "documentUrl"
+ ]
+ },
+ "privacyPolicy": {
+ "type": "object",
+ "title": "Privacy Policy Agreement",
+ "properties": {
+ "acknowledgment": {
+ "type": "boolean",
+ "title": "Privacy Policy Acknowledgment",
+ "description": "I acknowledge and agree that any data I share will be processed in accordance with the Catalyst FCS Privacy Policy",
+ "const": true
+ },
+ "version": {
+ "type": "string",
+ "title": "Privacy Policy Version",
+ "description": "Version of the Privacy Policy being acknowledged",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$",
+ "examples": [
+ "1.0.0",
+ "2.1.3"
+ ]
+ },
+ "documentUrl": {
+ "type": "string",
+ "title": "Privacy Policy URL",
+ "description": "URL to the specific version of privacy policy",
+ "format": "uri",
+ "pattern": "^https://[\\w\\-\\.]+\\.[a-zA-Z]{2,}/.*$",
+ "contentMediaType": "text/html"
+ },
+ "timestamp": {
+ "type": "string",
+ "title": "Acknowledgment Timestamp",
+ "description": "When the privacy policy was acknowledged",
+ "format": "date-time",
+ "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]+)?(Z|[+-][0-9]{2}:[0-9]{2})$",
+ "examples": [
+ "2024-01-20T15:30:00Z"
+ ]
+ }
+ },
+ "required": [
+ "acknowledgment",
+ "version",
+ "timestamp",
+ "documentUrl"
+ ]
+ },
+ "intellectualProperty": {
+ "type": "object",
+ "title": "Intellectual Property Declaration",
+ "properties": {
+ "acknowledgment": {
+ "type": "boolean",
+ "title": "IP Rights Acknowledgment",
+ "description": "I confirm that I have the necessary rights to all intellectual property included in this proposal",
+ "const": true
+ },
+ "details": {
+ "type": "string",
+ "title": "IP Details",
+ "description": "Additional details about intellectual property rights (if applicable)",
+ "maxLength": 1000,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
+ },
+ "attachments": {
+ "type": "array",
+ "title": "IP Documentation",
+ "description": "Supporting documentation for IP rights (if applicable)",
+ "items": {
+ "type": "object",
+ "properties": {
+ "documentType": {
+ "type": "string",
+ "enum": [
+ "patent",
+ "trademark",
+ "copyright",
+ "license",
+ "other"
+ ],
+ "description": "Type of IP documentation"
+ },
+ "documentUrl": {
+ "type": "string",
+ "format": "uri",
+ "pattern": "^https://[\\w\\-\\.]+\\.[a-zA-Z]{2,}/.*$",
+ "contentMediaType": "application/pdf"
+ },
+ "description": {
+ "type": "string",
+ "maxLength": 500,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
+ }
+ },
+ "required": [
+ "documentType",
+ "documentUrl",
+ "description"
+ ]
+ },
+ "maxItems": 10
+ },
+ "timestamp": {
+ "type": "string",
+ "title": "Acknowledgment Timestamp",
+ "description": "When the IP declaration was made",
+ "format": "date-time",
+ "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]+)?(Z|[+-][0-9]{2}:[0-9]{2})$",
+ "examples": [
+ "2024-01-20T15:30:00Z"
+ ]
+ }
+ },
+ "required": [
+ "acknowledgment",
+ "timestamp"
+ ]
+ },
+ "compliance": {
+ "type": "object",
+ "title": "Compliance Declaration",
+ "properties": {
+ "legalCompliance": {
+ "type": "boolean",
+ "title": "Legal Compliance",
+ "description": "I confirm that my proposal complies with all applicable laws and regulations",
+ "const": true
+ },
+ "noConflictOfInterest": {
+ "type": "boolean",
+ "title": "No Conflict of Interest",
+ "description": "I confirm that there are no undisclosed conflicts of interest",
+ "const": true
+ },
+ "accurateInformation": {
+ "type": "boolean",
+ "title": "Information Accuracy",
+ "description": "I confirm that all information provided is accurate and complete",
+ "const": true
+ },
+ "jurisdictions": {
+ "type": "array",
+ "title": "Applicable Jurisdictions",
+ "description": "List of jurisdictions where compliance is declared",
+ "items": {
+ "type": "string",
+ "pattern": "^[A-Z]{2}$",
+ "description": "ISO 3166-1 alpha-2 country code"
+ },
+ "minItems": 1,
+ "uniqueItems": true
+ },
+ "timestamp": {
+ "type": "string",
+ "title": "Acknowledgment Timestamp",
+ "description": "When the compliance declaration was made",
+ "format": "date-time",
+ "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]+)?(Z|[+-][0-9]{2}:[0-9]{2})$",
+ "examples": [
+ "2024-01-20T15:30:00Z"
+ ]
+ }
+ },
+ "required": [
+ "legalCompliance",
+ "noConflictOfInterest",
+ "accurateInformation",
+ "jurisdictions",
+ "timestamp"
+ ]
+ },
+ "additionalAcknowledgments": {
+ "type": "array",
+ "title": "Additional Acknowledgments",
+ "description": "Any additional acknowledgments required for specific proposal types",
+ "items": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "title": "Acknowledgment Type",
+ "minLength": 5,
+ "maxLength": 100,
+ "pattern": "^[a-zA-Z][a-zA-Z0-9_\\-\\.]*$"
+ },
+ "acknowledgment": {
+ "type": "boolean",
+ "title": "Acknowledgment",
+ "const": true
+ },
+ "description": {
+ "type": "string",
+ "title": "Description",
+ "description": "Detailed description of what is being acknowledged",
+ "minLength": 10,
+ "maxLength": 500,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
+ },
+ "documentUrl": {
+ "type": "string",
+ "title": "Reference Document",
+ "description": "URL to the document being acknowledged",
+ "format": "uri",
+ "pattern": "^https://[\\w\\-\\.]+\\.[a-zA-Z]{2,}/.*$",
+ "contentMediaType": "text/html"
+ },
+ "timestamp": {
+ "type": "string",
+ "title": "Acknowledgment Timestamp",
+ "format": "date-time",
+ "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]+)?(Z|[+-][0-9]{2}:[0-9]{2})$",
+ "examples": [
+ "2024-01-20T15:30:00Z"
+ ]
+ }
+ },
+ "required": [
+ "type",
+ "acknowledgment",
+ "description",
+ "timestamp"
+ ]
+ }
+ }
+ },
+ "required": [
+ "fundRules",
+ "termsAndConditions",
+ "privacyPolicy",
+ "intellectualProperty",
+ "compliance"
+ ]
+}
+}
+}
+ "impact": {
+ "type": "object",
+ "title": "Project Impact",
+ "description": "Describe the expected impact of your project",
+ "properties": {
+ "timeframe": {
+ "type": "string",
+ "enum": [
+ "Short-term (0-6 months)",
+ "Medium-term (6-18 months)",
+ "Long-term (18+ months)"
+ ],
+ "title": "Impact Timeframe",
+ "description": "Expected timeframe to see meaningful impact"
+ },
+ "scale": {
+ "type": "string",
+ "enum": [
+ "Local",
+ "Regional",
+ "Global"
+ ],
+ "title": "Impact Scale",
+ "description": "Geographic scale of impact"
+ },
+ "metrics": {
+ "type": "array",
+ "title": "Impact Metrics",
+ "description": "Key metrics to measure project success",
+ "items": {
+ "type": "object",
+ "properties": {
+ "metric": {
+ "type": "string",
+ "title": "Metric Name",
+ "description": "Name of the metric",
+ "maxLength": 100,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
+ },
+ "target": {
+ "type": "string",
+ "title": "Target Value",
+ "description": "Target value or goal for this metric",
+ "maxLength": 100,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
+ },
+ "measurement": {
+ "type": "string",
+ "title": "Measurement Method",
+ "description": "How this metric will be measured",
+ "maxLength": 200,
+ "pattern": "^[\\S\\s]*$",
+ "contentMediaType": "text/plain"
+ }
+ },
+ "required": [
+ "metric",
+ "target",
+ "measurement"
+ ]
+ },
+ "minItems": 1,
+ "maxItems": 5
+ }
+ },
+ "required": [
+ "timeframe",
+ "scale",
+ "metrics"
+ ]
+ }
+},
+"required": [
+ "primaryCategory",
+ "subCategory",
+ "tags",
+ "impact"
+]
+},
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/readModifications.md b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/readModifications.md
index 055d0b00db9..96c4254bbb0 100644
--- a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/readModifications.md
+++ b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/readModifications.md
@@ -1,207 +1,215 @@
# F14-Generic Proposal Template
+
## New Fields added to the proposal template
**Problem:**
- + Statement
- + Impact (select):
- + "Technical Infrastructure",
- + "User Experience",
- + "Developer Tooling",
- + "Community Growth",
- + "Economic Sustainability",
- + "Interoperability",
- + "Security",
- + "Scalability",
- + "Education",
- + "Adoption"
+
+* Statement
+* Impact (select):
+ * "Technical Infrastructure",
+ * "User Experience",
+ * "Developer Tooling",
+ * "Community Growth",
+ * "Economic Sustainability",
+ * "Interoperability",
+ * "Security",
+ * "Scalability",
+ * "Education",
+ * "Adoption"
**Solution:**
- + Summary
- + Approach
- + Innovative aspects
+
+* Summary
+* Approach
+* Innovative aspects
**Supporting links:**
- + Links
- + Url
- + Description
- + Type (select):
- + "GitHub Repository",
- + "Documentation",
- + "Whitepaper",
- + "Website",
- + "Marketing Material",
- + "Technical Specification",
- + "Research Paper",
- + "Blog Post",
- + "Social Media",
- + "Other"
- + Main Repository link
- + Documentation link
+
+* Links
+ * URL
+ * Description
+ * Type (select):
+ * "GitHub Repository",
+ * "Documentation",
+ * "Whitepaper",
+ * "Website",
+ * "Marketing Material",
+ * "Technical Specification",
+ * "Research Paper",
+ * "Blog Post",
+ * "Social Media",
+ * "Other"
+* Main Repository link
+* Documentation link
**Dependencies**
- + detail:
- + name
- + description
- + type:
- + "Technical"
- + "Organizational"
- + "Legal"
- + "Financial"
- + "Other"
- + mitigationPlan
+
+* detail:
+ * name
+ * description
+ * type:
+ * "Technical"
+ * "Organizational"
+ * "Legal"
+ * "Financial"
+ * "Other"
+ * mitigationPlan
**Horizons:**
- + tags:
- + additional tags to be entered for the project -> on top of category and subcategory
- + Impact:
- + timeframe:
- + "Short-term (0-6 months)"
- + "Medium-term (6-18 months)"
- + "Long-term (18+ months)"
- + scale:
- + "Local",
- + "Regional",
- + "Global"
- + metrics:
- + "metric name",
- + "target",
- + "measurement"
-
-- Product Details:
- - Solution:
- - description
- + unique value proposition
- + target audience
- + implementation approach
- - Impact:
- + communityBenefit
- + Metrics
- + name
- + description
- + target
- + measurement
- + Project outputs
- - Capability:
- + Team Experience
- + Feasibility Approach
- + Fund Management: (How will you ensure proper management and accountability of funds?)
-
+
+* tags:
+ * additional tags to be entered for the project -> on top of category and subcategory
+* Impact:
+ * timeframe:
+ * "Short-term (0-6 months)"
+ * "Medium-term (6-18 months)"
+ * "Long-term (18+ months)"
+ * scale:
+ * "Local",
+ * "Regional",
+ * "Global"
+ * metrics:
+ * "metric name",
+ * "target",
+ * "measurement"
+
+* Product Details:
+ * Solution:
+ * description
+ * unique value proposition
+ * target audience
+ * implementation approach
+ * Impact:
+ * communityBenefit
+ * Metrics
+ * name
+ * description
+ * target
+ * measurement
+ * Project outputs
+ * Capability:
+ * Team Experience
+ * Feasibility Approach
+ * Fund Management: (How will you ensure proper management and accountability of funds?)
**Milestones:**
- + milestonesConfig:
- + grantAmount
- + numberOfMilestones
- + milestonesList:
- - milestone:
- - title
- + description
- + deliverables
- + name
- + description
- + type
- + "Documentation"
- + "Software"
- + "Report"
- + "Presentation"
- + "Video"
- + "Other"
- + evidenceOfCompletion
- + type
- + "Code Repository"
- + "Documentation"
- + "Demo Video"
- + "Test Results"
- + "Metrics Report"
- + "User Feedback"
- + "Other"
- + description
- + timeline
- + startDate
- + endDate
- + durationInWeeks
- + budget
- + amount
- + breakdown
- + category
- + "Development"
- + "Design"
- + "Marketing"
- + "Operations"
- + "Other"
- + amount
- + description
+
+* milestonesConfig:
+ * grantAmount
+ * numberOfMilestones
+* milestonesList:
+ * milestone:
+ * title
+ * description
+ * deliverables
+ * name
+ * description
+ * type
+ * "Documentation"
+ * "Software"
+ * "Report"
+ * "Presentation"
+ * "Video"
+ * "Other"
+ * evidenceOfCompletion
+ * type
+ * "Code Repository"
+ * "Documentation"
+ * "Demo Video"
+ * "Test Results"
+ * "Metrics Report"
+ * "User Feedback"
+ * "Other"
+ * description
+ * timeline
+ * startDate
+ * endDate
+ * durationInWeeks
+ * budget
+ * amount
+ * breakdown
+ * category
+ * "Development"
+ * "Design"
+ * "Marketing"
+ * "Operations"
+ * "Other"
+ * amount
+ * description
**Final Pitch**
- + team
- + members
- + name
- + role
- + expertise
- + experience
- + links
- + type
- + url
- + description
- + budget
- + total budget
- + budget categories
- + category:
- + "Development",
- + "Design",
- + "Marketing",
- + "Operations",
- + "Research",
- + "Community Management",
- + "Legal",
- + "Other"
- + amount
- + description
+* team
+ * members
+ * name
+ * role
+ * expertise
+ * experience
+ * links
+ * type
+ * url
+ * description
+* budget
+ * total budget
+ * budget categories
+ * category:
+ * "Development",
+ * "Design",
+ * "Marketing",
+ * "Operations",
+ * "Research",
+ * "Community Management",
+ * "Legal",
+ * "Other"
+ * amount
+ * description
**Value for money**
- + costBenefitAnalysis
- + longTermValue
- + communityBenefits
+
+* costBenefitAnalysis
+* longTermValue
+* communityBenefits
**Mandatory Acknowledgments**
- + Fund Rules
- + Acknowledgment
- + Version
- + Timestamp
+
+* Fund Rules
+ * Acknowledgment
+ * Version
+ * Timestamp
- + Terms And Conditions
- + Acknowledgment
- + Version
- + DocumentUrl
- + Timestamp
+* Terms And Conditions
+ * Acknowledgment
+ * Version
+ * DocumentUrl
+ * Timestamp
- + Privacy Policy
- + Acknowledgment
- + Version
- + DocumentUrl
- + Timestamp
+* Privacy Policy
+ * Acknowledgment
+ * Version
+ * DocumentUrl
+ * Timestamp
- + Intellectual Property
- + Acknowledgment
- + Details
- + Attachments
- + Document Type
- + "patent",
- + "trademark",
- + "copyright",
- + "license",
- + "other"
- + Document Url
- + Description
+* Intellectual Property
+ * Acknowledgment
+ * Details
+ * Attachments
+ * Document Type
+ * "patent",
+ * "trademark",
+ * "copyright",
+ * "license",
+ * "other"
+ * Document Url
+ * Description
- + Compliances (checkboxes)
- + Legal Compliance
- + No Conflict Of Interest
- + Accurate Information
- + Jurisdictions
- + Timestamp
+* Compliances (checkboxes)
+ * Legal Compliance
+ * No Conflict Of Interest
+ * Accurate Information
+ * Jurisdictions
+ * Timestamp
- + Additional Acknowledgments
- + Type
- + Acknowledgment
- + Description
- + Document Url
- + Timestamp
\ No newline at end of file
+* Additional Acknowledgments
+ * Type
+ * Acknowledgment
+ * Description
+ * Document Url
+ * Timestamp
From 428885d997134d7b29f8c6ca3972e42912a16d9d Mon Sep 17 00:00:00 2001
From: Nathan Bogale
Date: Sun, 8 Dec 2024 12:04:38 +0300
Subject: [PATCH 14/25] fix: CI check failure, over spelling and markdown
---
...38-9258-4fbc-a62e-7faa6e58318f.schema.json | 8 +-
.../F14-Generic/example.proposal.json | 212 ++++-------------
.../proposal/F14-Generic/readModifications.md | 215 ------------------
3 files changed, 44 insertions(+), 391 deletions(-)
delete mode 100644 docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/readModifications.md
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
index dc5812c5be1..82d3cfb24c5 100644
--- a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
+++ b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
@@ -269,13 +269,13 @@
"title": "Translation Information",
"description": "Information about the proposal's language and translation status",
"properties": {
- "translated": {
+ "isTranslated": {
"$ref": "#/definitions/yesNoChoice",
"title": "Auto-translated Status",
"description": "Indicate if your proposal has been auto-translated into English from another language",
"x-guidance": "Tick YES if your proposal has been auto-translated into English from another language so readers are reminded that your proposal has been translated, and that they should be tolerant of any language imperfections. Tick NO if your proposal has not been auto-translated into English from another language
"
},
- "original": {
+ "originalLanguage": {
"$ref": "#/definitions/singleLineTextEntry",
"title": "Original Language",
"description": "If auto-translated, specify the original language of your proposal",
@@ -287,7 +287,7 @@
"French"
]
},
- "notes": {
+ "translationNotes": {
"$ref": "#/definitions/multiLineTextEntry",
"title": "Translation Notes",
"description": "Additional notes about the translation or original language content",
@@ -391,7 +391,7 @@
"approach"
]
},
- "SupportingLinks": {
+ "supportingLinks": {
"$ref": "#/definitions/section",
"title": "Supporting Documentation",
"description": "Additional resources and documentation for your proposal",
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/example.proposal.json b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/example.proposal.json
index 4b2d77cdbc3..17aafe4cd15 100644
--- a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/example.proposal.json
+++ b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/example.proposal.json
@@ -18,9 +18,9 @@
"duration": 6
},
"translation": {
- "translated": false,
- "original": "English",
- "notes": "Original proposal in English"
+ "isTranslated": true,
+ "originalLanguage": "Spanish",
+ "translationNotes": "Translated using DeepL with manual review"
},
"problem": {
"statement": "Current challenge in the Cardano ecosystem...",
@@ -38,199 +38,67 @@
"Automated integration tools"
]
},
- "SupportingLinks": {
- "links": [
- {
- "url": "https://github.com/example/project",
- "type": "GitHub Repository",
- "description": "Project's main repository"
- }
- ],
+ "supportingLinks": {
"mainRepository": "https://github.com/example/project",
- "documentation": "https://docs.example.com"
+ "documentation": "https://docs.example.com",
+ "other": [
+ "https://github.com/example/project"
+ ]
+ },
+ "dependencies": {
+ "details": []
+ },
+ "open_source": {
+ "source_code": "MIT",
+ "documentation": "MIT",
+ "note": "All project outputs will be open source under MIT license"
}
},
"horizons": {
- "category": {
- "primaryCategory": "Development & Tools",
- "subCategory": "Developer Tools"
- },
- "tags": [
- "defi",
- "developer-tools",
- "infrastructure"
- ],
- "impact": {
- "timeframe": "Medium-term (6-18 months)",
- "scale": "Global",
- "metrics": [
- {
- "metric": "Developer Adoption",
- "target": "500 active developers",
- "measurement": "GitHub analytics"
- }
- ]
+ "theme": {
+ "grouped_tag": {
+ "group": "DeFi",
+ "tag": "Staking"
+ }
}
},
- "proposalDetails": {
+ "details": {
"solution": {
- "description": "Our solution provides a comprehensive toolkit...",
- "uniqueValue": "First integrated testing framework for Cardano",
- "targetAudience": [
- "Cardano Developers",
- "DApp Teams"
- ],
- "implementation": "We will use an agile development approach..."
+ "solution": "Our solution provides a comprehensive toolkit..."
},
"impact": {
- "communityBenefit": "Significantly reduces development time and improves code quality",
- "metrics": [
- {
- "name": "Developer Adoption",
- "description": "Number of active developers using the toolkit",
- "target": "500 developers",
- "measurement": "GitHub analytics and usage statistics"
- }
- ],
- "outputs": [
- "Testing Framework",
- "Documentation",
- "Training Materials"
- ]
+ "impact": "The project will significantly impact developer productivity..."
},
- "capability": {
- "teamExperience": "Our team has extensive experience in blockchain development...",
- "feasibilityApproach": "We have already developed a proof of concept...",
- "fundManagement": "Funds will be managed through a transparent process..."
+ "feasibility": {
+ "feasibility": "Our team has extensive experience in blockchain development..."
}
},
"milestones": {
"milestones": {
"declared": [
- "a",
- "bb",
- "cccccccccccccccccccccccc",
- "dd",
- "eee",
- "fff"
+ "# Initial Setup and Planning\n\nProject setup and infrastructure...",
+ "# Core Development\n\nImplementation of main features...",
+ "# Testing and Documentation\n\nComprehensive testing and documentation...",
+ "# Final Release\n\nProject completion and deployment with Project Close-out Report and Video..."
]
}
},
- "milestonez": {
- "milestonesConfig": {
- "grantAmount": 150000,
- "numberOfMilestones": 4
- },
- "milestonesList": [
- {
- "title": "Initial Setup and Planning",
- "description": "Project setup and detailed planning phase",
- "deliverables": [
- {
- "name": "Project Plan",
- "description": "Detailed project planning documentation",
- "type": "Documentation"
- }
- ],
- "acceptanceCriteria": [
- "Completed project plan",
- "Technical specifications approved"
- ],
- "evidenceOfCompletion": [
- {
- "type": "Documentation",
- "description": "Project planning documents and specifications"
- }
- ],
- "timeline": {
- "startDate": "2024-03-01",
- "endDate": "2024-04-01",
- "durationInWeeks": 4
- },
- "budget": {
- "amount": 37500,
- "breakdown": [
- {
- "category": "Development",
- "amount": 30000,
- "description": "Initial development work"
- }
- ]
- }
- }
- ]
- },
- "finalPitch": {
+ "pitch": {
"team": {
- "members": [
- {
- "name": "John Doe",
- "role": "Project Lead",
- "expertise": [
- "Blockchain Development",
- "Smart Contracts"
- ],
- "experience": "10 years in software development",
- "links": [
- {
- "type": "GitHub",
- "url": "https://github.com/johndoe",
- "description": "GitHub Profile"
- }
- ]
- }
- ]
+ "who": "Our team consists of experienced blockchain developers..."
},
"budget": {
- "totalBudget": 150000,
- "categories": [
- {
- "category": "Development",
- "amount": 100000,
- "description": "Core development team costs"
- }
- ]
+ "costs": "Budget breakdown:\n- Development: 70%\n- Testing: 15%\n- Documentation: 15%"
},
- "valueProposition": {
- "costBenefitAnalysis": "The project provides significant value...",
- "longTermValue": "The solution will continue to benefit the ecosystem...",
- "communityBenefits": [
- "Increased developer productivity",
- "Better code quality"
- ]
+ "value": {
+ "note": "This project provides excellent value for money..."
}
},
- "mandatoryAcknowledgments": {
- "fundRules": {
- "acknowledgment": true,
- "version": "F14",
- "timestamp": "2024-01-20T15:30:00Z"
- },
- "termsAndConditions": {
- "acknowledgment": true,
- "version": "1.0.0",
- "documentUrl": "https://cardano.org/terms",
- "timestamp": "2024-01-20T15:30:00Z"
- },
- "privacyPolicy": {
- "acknowledgment": true,
- "version": "1.0.0",
- "documentUrl": "https://cardano.org/privacy",
- "timestamp": "2024-01-20T15:30:00Z"
- },
- "intellectualProperty": {
- "acknowledgment": true,
- "timestamp": "2024-01-20T15:30:00Z"
- },
- "compliance": {
- "legalCompliance": true,
- "noConflictOfInterest": true,
- "accurateInformation": true,
- "jurisdictions": [
- "US",
- "GB"
- ],
- "timestamp": "2024-01-20T15:30:00Z"
+ "agreements": {
+ "mandatory": {
+ "fund_rules": true,
+ "terms_and_conditions": true,
+ "privacy_policy": true
}
}
}
\ No newline at end of file
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/readModifications.md b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/readModifications.md
deleted file mode 100644
index 96c4254bbb0..00000000000
--- a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/readModifications.md
+++ /dev/null
@@ -1,215 +0,0 @@
-# F14-Generic Proposal Template
-
-## New Fields added to the proposal template
-
-**Problem:**
-
-* Statement
-* Impact (select):
- * "Technical Infrastructure",
- * "User Experience",
- * "Developer Tooling",
- * "Community Growth",
- * "Economic Sustainability",
- * "Interoperability",
- * "Security",
- * "Scalability",
- * "Education",
- * "Adoption"
-
-**Solution:**
-
-* Summary
-* Approach
-* Innovative aspects
-
-**Supporting links:**
-
-* Links
- * URL
- * Description
- * Type (select):
- * "GitHub Repository",
- * "Documentation",
- * "Whitepaper",
- * "Website",
- * "Marketing Material",
- * "Technical Specification",
- * "Research Paper",
- * "Blog Post",
- * "Social Media",
- * "Other"
-* Main Repository link
-* Documentation link
-
-**Dependencies**
-
-* detail:
- * name
- * description
- * type:
- * "Technical"
- * "Organizational"
- * "Legal"
- * "Financial"
- * "Other"
- * mitigationPlan
-
-**Horizons:**
-
-* tags:
- * additional tags to be entered for the project -> on top of category and subcategory
-* Impact:
- * timeframe:
- * "Short-term (0-6 months)"
- * "Medium-term (6-18 months)"
- * "Long-term (18+ months)"
- * scale:
- * "Local",
- * "Regional",
- * "Global"
- * metrics:
- * "metric name",
- * "target",
- * "measurement"
-
-* Product Details:
- * Solution:
- * description
- * unique value proposition
- * target audience
- * implementation approach
- * Impact:
- * communityBenefit
- * Metrics
- * name
- * description
- * target
- * measurement
- * Project outputs
- * Capability:
- * Team Experience
- * Feasibility Approach
- * Fund Management: (How will you ensure proper management and accountability of funds?)
-
-**Milestones:**
-
-* milestonesConfig:
- * grantAmount
- * numberOfMilestones
-* milestonesList:
- * milestone:
- * title
- * description
- * deliverables
- * name
- * description
- * type
- * "Documentation"
- * "Software"
- * "Report"
- * "Presentation"
- * "Video"
- * "Other"
- * evidenceOfCompletion
- * type
- * "Code Repository"
- * "Documentation"
- * "Demo Video"
- * "Test Results"
- * "Metrics Report"
- * "User Feedback"
- * "Other"
- * description
- * timeline
- * startDate
- * endDate
- * durationInWeeks
- * budget
- * amount
- * breakdown
- * category
- * "Development"
- * "Design"
- * "Marketing"
- * "Operations"
- * "Other"
- * amount
- * description
-**Final Pitch**
-* team
- * members
- * name
- * role
- * expertise
- * experience
- * links
- * type
- * url
- * description
-* budget
- * total budget
- * budget categories
- * category:
- * "Development",
- * "Design",
- * "Marketing",
- * "Operations",
- * "Research",
- * "Community Management",
- * "Legal",
- * "Other"
- * amount
- * description
-
-**Value for money**
-
-* costBenefitAnalysis
-* longTermValue
-* communityBenefits
-
-**Mandatory Acknowledgments**
-
-* Fund Rules
- * Acknowledgment
- * Version
- * Timestamp
-
-* Terms And Conditions
- * Acknowledgment
- * Version
- * DocumentUrl
- * Timestamp
-
-* Privacy Policy
- * Acknowledgment
- * Version
- * DocumentUrl
- * Timestamp
-
-* Intellectual Property
- * Acknowledgment
- * Details
- * Attachments
- * Document Type
- * "patent",
- * "trademark",
- * "copyright",
- * "license",
- * "other"
- * Document Url
- * Description
-
-* Compliances (checkboxes)
- * Legal Compliance
- * No Conflict Of Interest
- * Accurate Information
- * Jurisdictions
- * Timestamp
-
-* Additional Acknowledgments
- * Type
- * Acknowledgment
- * Description
- * Document Url
- * Timestamp
From 59e8a998dc1067ab6994cd7ed98bc8c26b1646d4 Mon Sep 17 00:00:00 2001
From: Nathan Bogale
Date: Mon, 9 Dec 2024 21:30:27 +0300
Subject: [PATCH 15/25] fix: added first wave of x-orders to ssegments and
sections
---
...38-9258-4fbc-a62e-7faa6e58318f.schema.json | 50 +++++++++++++------
1 file changed, 34 insertions(+), 16 deletions(-)
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
index 82d3cfb24c5..642f89b6939 100644
--- a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
+++ b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
@@ -198,7 +198,7 @@
"$ref": "#/definitions/dropDownSingleSelect",
"title": "Are you delivering this project as an individual or as an entity (whether formally incorporated or not)",
"description": "Are you delivering this project as an individual or as an entity (whether formally incorporated or not)",
- "x-mad-guidance": "Please select from one of the following:
- Individual
- Entity (Incorporated)
- Entity (Not Incorporated)
",
+ "x-guidance": "Please select from one of the following:
- Individual
- Entity (Incorporated)
- Entity (Not Incorporated)
",
"enum": [
"Individual",
"Entity (Incorporated)",
@@ -218,13 +218,15 @@
"required": [
"applicant",
"type"
- ]
+ ],
+ "x-order": ["applicant", "type", "coproposers"]
}
},
"required": [
"title",
"proposer"
- ]
+ ],
+ "x-order": ["title", "proposer"]
},
"summary": {
"$ref": "#/definitions/segment",
@@ -246,7 +248,8 @@
},
"required": [
"requestedFunds"
- ]
+ ],
+ "x-order": ["requestedFunds"]
},
"time": {
"$ref": "#/definitions/section",
@@ -494,9 +497,20 @@
"required": [
"source_code",
"documentation"
- ]
+ ],
+ "x-order": ["source_code", "documentation", "note"]
}
- }
+ },
+ "x-order": [
+ "budget",
+ "time",
+ "translation",
+ "problem",
+ "solution",
+ "supportingLinks",
+ "dependencies",
+ "open_source"
+ ]
},
"horizons": {
"$ref": "#/definitions/segment",
@@ -752,9 +766,11 @@
}
]
}
- }
+ },
+ "x-order": ["theme"]
}
- }
+ },
+ "x-order": ["theme"]
},
"details": {
"$ref": "#/definitions/segment",
@@ -799,7 +815,8 @@
}
}
}
- }
+ },
+ "x-order": ["solution", "impact", "feasibility"]
},
"milestones": {
"$ref": "#/definitions/segment",
@@ -814,9 +831,11 @@
"minItems": 3,
"maxItems": 6
}
- }
+ },
+ "x-order": ["declared"]
}
- }
+ },
+ "x-order": ["milestones"]
},
"pitch": {
"$ref": "#/definitions/segment",
@@ -861,7 +880,8 @@
}
}
}
- }
+ },
+ "x-order": ["team", "budget", "value"]
},
"agreements": {
"$ref": "#/definitions/segment",
@@ -899,9 +919,7 @@
]
}
},
- "x-order": [
- "mandatory"
- ]
+ "x-order": ["mandatory"]
}
},
"x-order": [
@@ -911,6 +929,6 @@
"details",
"milestones",
"pitch",
- "agreement"
+ "agreements"
]
}
\ No newline at end of file
From 3cc0b7ffa555dcd8d3de04b936c1345720d591a6 Mon Sep 17 00:00:00 2001
From: Nathan Bogale
Date: Thu, 12 Dec 2024 17:51:44 +0300
Subject: [PATCH 16/25] fix: Translation: added originalDocumentLink, if/then
condition modified
---
...38-9258-4fbc-a62e-7faa6e58318f.schema.json | 68 +++++++++++--------
1 file changed, 40 insertions(+), 28 deletions(-)
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
index 642f89b6939..780593af2ba 100644
--- a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
+++ b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
@@ -282,44 +282,56 @@
"$ref": "#/definitions/singleLineTextEntry",
"title": "Original Language",
"description": "If auto-translated, specify the original language of your proposal",
- "minLength": 2,
- "maxLength": 50,
- "examples": [
- "Spanish",
+ "enum": [
+ "Arabic",
+ "Chinese",
+ "French",
+ "German",
+ "Indonesian",
+ "Italian",
"Japanese",
- "French"
+ "Korean",
+ "Portuguese",
+ "Russian",
+ "Spanish",
+ "Turkish",
+ "Vietnamese",
+ "Other"
]
},
- "translationNotes": {
- "$ref": "#/definitions/multiLineTextEntry",
- "title": "Translation Notes",
- "description": "Additional notes about the translation or original language content",
- "maxLength": 500
+ "originalDocumentLink": {
+ "$ref": "#/definitions/singleLineHttpsURLEntry",
+ "title": "Original Document Link",
+ "description": "Provide a link to the original proposal document in its original language"
}
},
- "required": [
- "isTranslated"
- ],
- "dependencies": {
- "originalLanguage": [
- "isTranslated"
- ],
- "translationNotes": [
- "isTranslated"
- ]
- },
"if": {
"properties": {
- "isTranslated": {
- "const": true
- }
+ "isTranslated": { "const": "Yes" }
}
},
"then": {
- "required": [
- "originalLanguage"
- ]
- }
+ "required": ["originalLanguage", "originalDocumentLink"],
+ "properties": {
+ "originalLanguage": {
+ "description": "Original language is required when the proposal is translated"
+ },
+ "originalDocumentLink": {
+ "description": "Link to the original document is required when the proposal is translated"
+ }
+ }
+ },
+ "else": {
+ "properties": {
+ "originalLanguage": {
+ "not": {}
+ },
+ "originalDocumentLink": {
+ "not": {}
+ }
+ }
+ },
+ "required": ["isTranslated"]
},
"problem": {
"$ref": "#/definitions/section",
From 9a02d58a2a8b67c17cfd35171b46ada0b8e448bb Mon Sep 17 00:00:00 2001
From: Nathan Bogale
Date: Sun, 15 Dec 2024 21:14:34 +0300
Subject: [PATCH 17/25] fix: milestones updated, added x-note to definitions,
minor structure fixes
---
...38-9258-4fbc-a62e-7faa6e58318f.schema.json | 151 +++++++++++++-----
1 file changed, 113 insertions(+), 38 deletions(-)
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
index 780593af2ba..7e28a70e995 100644
--- a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
+++ b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
@@ -13,49 +13,58 @@
"segment": {
"$comment": "UI - Logical Document Section Break.",
"type": "object",
- "additionalProperties": false
+ "additionalProperties": false,
+ "x-note": "Major sections of the proposal. Each segment contains sections of information grouped together."
},
"section": {
"$comment": "UI - Logical Document Sub-Section Break.",
"type": "object",
- "additionalProperties": false
+ "additionalProperties": false,
+ "x-note": "Subsections containing specific details about the proposal."
},
"singleLineTextEntry": {
"$comment": "UI - Single Line text entry without any markup or rich text capability.",
"type": "string",
"contentMediaType": "text/plain",
- "pattern": "^.*$"
+ "pattern": "^.*$",
+ "x-note": "Enter a single line of text. No formatting, line breaks, or special characters are allowed."
},
"singleLineHttpsURLEntry": {
"$comment": "UI - Single Line text entry for HTTPS Urls.",
"type": "string",
"format": "uri",
- "pattern": "^https:.*"
+ "pattern": "^https:.*",
+ "x-note": "Enter a valid HTTPS URL. Must start with 'https://' and be a complete, working web address."
},
"multiLineTextEntry": {
"$comment": "UI - Multiline text entry without any markup or rich text capability.",
"type": "string",
"contentMediaType": "text/plain",
- "pattern": "^[\\S\\s]*$"
+ "pattern": "^[\\S\\s]*$",
+ "x-note": "Enter multiple lines of plain text. You can use line breaks but no special formatting."
+
},
"multiLineTextEntryMarkdown": {
"$comment": "UI - Multiline text entry with Markdown content.",
"type": "string",
"contentMediaType": "text/markdown",
- "pattern": "^[\\S\\s]*$"
+ "pattern": "^[\\S\\s]*$",
+ "x-note": "Use Markdown formatting for rich text. Available formatting:\n- Headers: # for h1, ## for h2, etc.\n- Lists: * or - for bullets, 1. for numbered\n- Emphasis: *italic* or **bold**\n- Links: [text](url)\n- Code: `inline` or ```block```"
},
"dropDownSingleSelect": {
"$comment": "UI - Drop Down Selection of a single entry from the defined enum.",
"type": "string",
"contentMediaType": "text/plain",
"pattern": "^.*$",
- "format": "dropDownSingleSelect"
+ "format": "dropDownSingleSelect",
+ "x-note": "Select one option from the dropdown menu. Only one choice is allowed."
},
"multiSelect": {
"$comment": "UI - Multiselect from the given items.",
"type": "array",
"uniqueItems": true,
- "format": "multiSelect"
+ "format": "multiSelect",
+ "x-note": "Select multiple options from the dropdown menu. Multiple choices are allowed."
},
"singleLineTextEntryList": {
"$comment": "UI - A Growable List of single line text (no markup or richtext).",
@@ -66,7 +75,8 @@
"items": {
"$ref": "#/definitions/singleLineTextEntry",
"maxLength": 1024
- }
+ },
+ "x-note": "Add multiple single-line text entries. Each entry should be unique and under 1024 characters."
},
"multiLineTextEntryListMarkdown": {
"$comment": "UI - A Growable List of markdown formatted text fields.",
@@ -77,7 +87,8 @@
"items": {
"$ref": "#/definitions/multiLineTextEntryMarkdown",
"maxLength": 10240
- }
+ },
+ "x-note": "Add multiple markdown-formatted text entries. Each entry can include rich formatting and should be unique."
},
"singleLineHttpsURLEntryList": {
"$comment": "UI - A Growable List of HTTPS URLs.",
@@ -88,68 +99,79 @@
"items": {
"$ref": "#/definitions/singleLineHttpsURLEntry",
"maxLength": 1024
- }
+ },
+ "x-note": "Enter multiple HTTPS URLs. Each URL should be unique and under 1024 characters."
},
"nestedQuestionsList": {
"$comment": "UI - A Growable List of Questions. The contents are an object, that can have any UI elements within.",
"type": "array",
"format": "nestedQuestionsList",
"uniqueItems": true,
- "default": []
+ "default": [],
+ "x-note": "Add multiple questions. Each question should be unique."
},
"nestedQuestions": {
"$comment": "UI - The container for a nested question set.",
"type": "object",
"format": "nestedQuestions",
- "additionalProperties": false
+ "additionalProperties": false,
+ "x-note": "Add multiple questions. Each question should be unique."
},
"singleGroupedTagSelector": {
"$comment": "UI - A selector where a top level selection, gives a single choice from a list of tags.",
"type": "object",
"format": "singleGroupedTagSelector",
- "additionalProperties": false
+ "additionalProperties": false,
+ "x-note": "Select one option from the dropdown menu. Only one choice is allowed."
},
"tagGroup": {
"$comment": "UI - An individual group within a singleGroupedTagSelector.",
"type": "string",
"format": "tagGroup",
- "pattern": "^.*$"
+ "pattern": "^.*$",
+ "x-note": "Select one option from the dropdown menu. Only one choice is allowed."
},
"tagSelection": {
"$comment": "UI - An individual tag within the group of a singleGroupedTagSelector.",
"type": "string",
"format": "tagSelection",
- "pattern": "^.*$"
+ "pattern": "^.*$",
+ "x-note": "Select one option from the dropdown menu. Only one choice is allowed."
},
"tokenValueCardanoADA": {
"$comment": "UI - A Token Value denominated in Cardano ADA.",
"type": "integer",
- "format": "token:cardano:ada"
+ "format": "token:cardano:ada",
+ "x-note": "Enter the amount of Cardano ADA to be used in the proposal."
},
"durationInMonths": {
"$comment": "UI - A Duration represented in total months.",
"type": "integer",
- "format": "datetime:duration:months"
+ "format": "datetime:duration:months",
+ "x-note": "Enter the duration of the proposal in months."
},
"yesNoChoice": {
"$comment": "UI - A Boolean choice, represented as a Yes/No selection. Yes = true.",
"type": "boolean",
"format": "yesNoChoice",
- "default": false
+ "default": false,
+ "x-note": "Select Yes or No."
},
"agreementConfirmation": {
"$comment": "UI - A Boolean choice, defaults to `false` but its invalid if its not set to `true`.",
"type": "boolean",
"format": "agreementConfirmation",
"default": false,
- "const": true
+ "const": true,
+ "x-note": "Select Yes or No."
},
"spdxLicenseOrURL": {
"$comment": "UI - Drop Down Selection of any valid SPDX Identifier. This is a complex type, it should let the user select one of the valid SPDX licenses, or enter a URL of the license if its proprietary. In the form its just a string.",
"type": "string",
"contentMediaType": "text/plain",
"pattern": "^.*$",
- "format": "spdxLicenseOrURL"
+ "format": "spdxLicenseOrURL",
+ "x-note": "Select one option from the dropdown menu. Only one choice is allowed."
}
},
"type": "object",
@@ -489,7 +511,7 @@
"open_source": {
"$ref": "#/definitions/section",
"title": "Project Open Source",
- "description": "Will your project's output/be s fully open source? Open source refers to something people can modify and share because its design is publicly accessible.",
+ "description": "Will your project's output be fully open source? Open source refers to something people can modify and share because its design is publicly accessible.",
"x-guidance": "Open source software is software with source code that anyone can inspect, modify, and enhance. Conversely, only the original authors of proprietary software can legally copy, inspect, and alter that software
",
"properties": {
"source_code": {
@@ -503,7 +525,7 @@
"title": "More Information",
"description": "Please provide here more information on the open source status of your project outputs",
"maxLength": 500,
- "x-guidance": "If you did not answer PROPRIETARY to the above questions, the project should be open source-available throughout the entire lifecycle of the project with a declared open-source repository. Please indicate here the type of license you intend to use for open source and provide any further information you feel is relevant to the open source status of your project outputs If only certain elements of your code will be open source please clarify which elements will be open source here. If you answered NO to the above question, please give further details as to why your projects outputs will not be open source METADATA
"
+ "x-guidance": "If you did not answer PROPRIETARY to the above questions, the project should be open source available throughout the entire lifecycle of the project with a declared open-source repository. Please indicate here the type of license you intend to use for open source and provide any further information you feel is relevant to the open source status of your project outputs If only certain elements of your code will be open source please clarify which elements will be open source here. If you answered NO to the above question, please give further details as to why your projects outputs will not be open source METADATA
"
}
},
"required": [
@@ -830,25 +852,78 @@
},
"x-order": ["solution", "impact", "feasibility"]
},
+"milestones": {
+ "$ref": "#/definitions/segment",
+ "title": "Milestones",
+ "properties": {
"milestones": {
- "$ref": "#/definitions/segment",
- "title": "Milestones",
+ "$ref": "#/definitions/section",
+ "title": "Project Milestones",
+ "description": "Each milestone must declare:
- A: Milestone outputs
- B: Acceptance criteria
- C: Evidence of completion
Requirements:
- For Grant Amounts up to 75k ada: minimum 3 milestones (2 + final)
- For Grant Amounts 75k-150k ada: minimum 4 milestones (3 + final)
- The final milestone must include Project Close-out Report and Video
",
"properties": {
- "milestones": {
- "$ref": "#/definitions/section",
- "description": "A clear set of milestones and acceptance criteria will demonstrate your capability to deliver the project as proposed. More guidance on submitting milestones as part of your project proposal can be found here.
Milestones guidance
- For Grant Amounts of up to 75k ada, at least 2 milestones, plus the final one including Project Close-out Report and Video, must be included (3 milestones in total)
- For Grant Amounts over 75k ada up to 150k ada, at least 3 milestones, plus the final one including Project Close-out Report and Video, must be included (4 milestones in total)
- For Grant Amounts over 150k ada up to 300k ada, at least 4 milestones, plus the final one including Project Close-out Report and Video, must be included (5 milestones in total)
- For Grant Amounts exceeding 300k ada, at least 5 milestones, plus the final one including Project Close-out Report and Video, must be included (6 milestones in total)
",
- "properties": {
- "declared": {
- "$ref": "#/definitions/multiLineTextEntryListMarkdown",
- "minItems": 3,
- "maxItems": 6
+ "milestone_list": {
+ "type": "array",
+ "title": "Milestones",
+ "description": "What are the key milestones you need to achieve in order to complete your project successfully?",
+ "x-guidance": "Milestone Requirements:
- For Grant Amounts of up to 75k ada: at least 2 milestones, plus the final one including Project Close-out Report and Video, must be included (3 milestones in total)
- For Grant Amounts over 75k ada up to 150k ada: at least 3 milestones, plus the final one including Project Close-out Report and Video, must be included (4 milestones in total)
- For Grant Amounts over 150k ada up to 300k ada: at least 4 milestones, plus the final one including Project Close-out Report and Video, must be included (5 milestones in total)
- For Grant Amounts exceeding 300k ada: at least 5 milestones, plus the final one including Project Close-out Report and Video, must be included (6 milestones in total)
",
+ "minItems": 3,
+ "maxItems": 6,
+ "items": {
+ "type": "object",
+ "required": ["title", "outputs", "acceptance_criteria", "evidence", "delivery_month", "cost"],
+ "properties": {
+ "title": {
+ "$ref": "#/definitions/singleLineTextEntry",
+ "title": "Milestone Title",
+ "description": "A clear, concise title for this milestone",
+ "maxLength": 100
+ },
+ "outputs": {
+ "$ref": "#/definitions/multiLineTextEntryMarkdown",
+ "title": "Milestone Outputs",
+ "description": "What will be delivered in this milestone",
+ "maxLength": 1000
+ },
+ "acceptance_criteria": {
+ "$ref": "#/definitions/multiLineTextEntryMarkdown",
+ "title": "Acceptance Criteria",
+ "description": "Specific conditions that must be met",
+ "maxLength": 1000
+ },
+ "evidence": {
+ "$ref": "#/definitions/multiLineTextEntryMarkdown",
+ "title": "Evidence of Completion",
+ "description": "How you will demonstrate achievement",
+ "maxLength": 1000
+ },
+ "delivery_month": {
+ "$ref": "#/definitions/durationInMonths",
+ "title": "Delivery Month",
+ "description": "The month when this milestone will be delivered",
+ "minimum": 1,
+ "maximum": 12
+ },
+ "cost": {
+ "$ref": "#/definitions/tokenValueCardanoADA",
+ "title": "Cost in ADA",
+ "description": "The cost of this milestone in ADA"
+ },
+ "progress": {
+ "$ref": "#/definitions/dropDownSingleSelect",
+ "title": "Progress Status",
+ "description": "Current status of the milestone",
+ "enum": ["Not Started", "In Progress", "Completed", "Delayed"],
+ "default": "Not Started"
+ }
}
- },
- "x-order": ["declared"]
+ }
}
},
- "x-order": ["milestones"]
- },
+ "required": ["milestone_list"]
+ }
+ },
+ "x-order": ["milestones"]
+},
"pitch": {
"$ref": "#/definitions/segment",
"title": "Final Pitch",
@@ -860,7 +935,7 @@
"who": {
"$ref": "#/definitions/multiLineTextEntryMarkdown",
"title": "Who is in the project team and what are their roles?",
- "description": "p>List your team, their Linkedin profiles (or similar) and state what aspect of the proposal’s work each team member will undertake.
If you are planning to recruit additional team members, please state what specific skills you will be looking for in the people you recruit, so readers can see that you understand what skills will be needed to complete the project.
You are expected to have already engaged the relevant members of the organizations referenced so you understand if they are willing and/or have capacity to support the project. If you have not taken any steps to engage with your team yet, it is likely that the resources will not be available if you are approved for funding, which can jeopardize the project before it has even begun. The Catalyst team cannot help with this, meaning you are expected to have understood the requirements and engaged the necessary people before submitting a proposal.
Have you engaged anyone on any of the technical group channels (eg Discord or Telegram), or do you have a direct line of communications with the people and resources required?
Important: Catalyst funding is not anonymous, and some level of ‘proof of life’ verifications will take place before initial funding is released. Also remember that your proposal will be publicly available, so make sure to obtain any consent required before including confidential or third party information.
All Project Participants must disclose their role and scope of services across any submitted proposals, even if they are not in the lead or co-proposer role, such as an implementer, vendor, service provider, etc. Failure to disclose this information may lead to disqualification from the current grant round.
",
+ "description": "List your team, their Linkedin profiles (or similar) and state what aspect of the proposal’s work each team member will undertake.
If you are planning to recruit additional team members, please state what specific skills you will be looking for in the people you recruit, so readers can see that you understand what skills will be needed to complete the project.
You are expected to have already engaged the relevant members of the organizations referenced so you understand if they are willing and/or have capacity to support the project. If you have not taken any steps to engage with your team yet, it is likely that the resources will not be available if you are approved for funding, which can jeopardize the project before it has even begun. The Catalyst team cannot help with this, meaning you are expected to have understood the requirements and engaged the necessary people before submitting a proposal.
Have you engaged anyone on any of the technical group channels (eg Discord or Telegram), or do you have a direct line of communications with the people and resources required?
Important: Catalyst funding is not anonymous, and some level of ‘proof of life’ verifications will take place before initial funding is released. Also remember that your proposal will be publicly available, so make sure to obtain any consent required before including confidential or third party information.
All Project Participants must disclose their role and scope of services across any submitted proposals, even if they are not in the lead or co-proposer role, such as an implementer, vendor, service provider, etc. Failure to disclose this information may lead to disqualification from the current grant round.
",
"minLength": 1,
"maxLength": 10240
}
From 3d81d9abf52fa5c051f6ec930aa9b52d9d9646cb Mon Sep 17 00:00:00 2001
From: Nathan Bogale
Date: Mon, 16 Dec 2024 17:41:19 +0300
Subject: [PATCH 18/25] fix: updated the example, translation example failing
---
...38-9258-4fbc-a62e-7faa6e58318f.schema.json | 2 +-
.../F14-Generic/example.proposal.json | 68 ++++++++++++++-----
2 files changed, 52 insertions(+), 18 deletions(-)
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
index 7e28a70e995..52d0592bb77 100644
--- a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
+++ b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
@@ -329,7 +329,7 @@
},
"if": {
"properties": {
- "isTranslated": { "const": "Yes" }
+ "isTranslated": { "const": true }
}
},
"then": {
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/example.proposal.json b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/example.proposal.json
index 17aafe4cd15..01710279147 100644
--- a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/example.proposal.json
+++ b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/example.proposal.json
@@ -5,9 +5,12 @@
"title": "Example Catalyst Proposal"
},
"proposer": {
- "applicant": "John Doe",
+ "applicant": "John Smith",
"type": "Individual",
- "coproposers": []
+ "coproposers": [
+ "Jane Doe",
+ "Bob Wilson"
+ ]
}
},
"summary": {
@@ -19,8 +22,8 @@
},
"translation": {
"isTranslated": true,
- "originalLanguage": "Spanish",
- "translationNotes": "Translated using DeepL with manual review"
+ "originalLanguage":"German",
+ "originalDocumentLink": "https://example.com/original-doc"
},
"problem": {
"statement": "Current challenge in the Cardano ecosystem...",
@@ -42,11 +45,19 @@
"mainRepository": "https://github.com/example/project",
"documentation": "https://docs.example.com",
"other": [
- "https://github.com/example/project"
+ "https://example.com/whitepaper",
+ "https://example.com/roadmap"
]
},
"dependencies": {
- "details": []
+ "details": [
+ {
+ "name": "External API Service",
+ "type": "Technical",
+ "description": "Integration with third-party API service",
+ "mitigationPlan": "Build fallback mechanisms and maintain alternative providers"
+ }
+ ]
},
"open_source": {
"source_code": "MIT",
@@ -64,34 +75,57 @@
},
"details": {
"solution": {
- "solution": "Our solution provides a comprehensive toolkit..."
+ "solution": "Our solution involves developing a comprehensive toolkit that will enhance the Cardano developer experience..."
},
"impact": {
- "impact": "The project will significantly impact developer productivity..."
+ "impact": "The project will significantly impact developer productivity by reducing development time and improving code quality..."
},
"feasibility": {
- "feasibility": "Our team has extensive experience in blockchain development..."
+ "feasibility": "Our team has extensive experience in blockchain development and has successfully delivered similar projects..."
}
},
"milestones": {
"milestones": {
- "declared": [
- "# Initial Setup and Planning\n\nProject setup and infrastructure...",
- "# Core Development\n\nImplementation of main features...",
- "# Testing and Documentation\n\nComprehensive testing and documentation...",
- "# Final Release\n\nProject completion and deployment with Project Close-out Report and Video..."
+ "milestone_list": [
+ {
+ "title": "Initial Setup and Planning",
+ "outputs": "Project infrastructure setup and detailed planning documents",
+ "acceptance_criteria": "- Development environment configured\n- Detailed project plan approved",
+ "evidence": "- GitHub repository setup\n- Documentation of infrastructure\n- Project planning documents",
+ "delivery_month": 1,
+ "cost": 30000,
+ "progress": "Not Started"
+ },
+ {
+ "title": "Core Development",
+ "outputs": "Implementation of main features",
+ "acceptance_criteria": "- Core features implemented\n- Unit tests passing",
+ "evidence": "- Code repository\n- Test results\n- Technical documentation",
+ "delivery_month": 3,
+ "cost": 60000,
+ "progress": "Not Started"
+ },
+ {
+ "title": "Final Release and Documentation",
+ "outputs": "Project completion, documentation, and Project Close-out Report and Video",
+ "acceptance_criteria": "- All features implemented and tested\n- Documentation complete\n- Close-out report and video delivered",
+ "evidence": "- Final release\n- Complete documentation\n- Close-out report and video",
+ "delivery_month": 6,
+ "cost": 60000,
+ "progress": "Not Started"
+ }
]
}
},
"pitch": {
"team": {
- "who": "Our team consists of experienced blockchain developers..."
+ "who": "Our team consists of experienced blockchain developers with proven track records..."
},
"budget": {
- "costs": "Budget breakdown:\n- Development: 70%\n- Testing: 15%\n- Documentation: 15%"
+ "costs": "Budget breakdown:\n- Development (70%): 105,000 ADA\n- Testing (15%): 22,500 ADA\n- Documentation (15%): 22,500 ADA"
},
"value": {
- "note": "This project provides excellent value for money..."
+ "note": "This project provides excellent value for money by delivering essential developer tools..."
}
},
"agreements": {
From 21f366b0808d1f1377f65bb9ea28a309c57376de Mon Sep 17 00:00:00 2001
From: Nathan Bogale
Date: Mon, 16 Dec 2024 19:38:11 +0300
Subject: [PATCH 19/25] fix: horizons grouping issue fixed
---
.../0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
index 52d0592bb77..afa71e375b5 100644
--- a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
+++ b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
@@ -121,7 +121,7 @@
"$comment": "UI - A selector where a top level selection, gives a single choice from a list of tags.",
"type": "object",
"format": "singleGroupedTagSelector",
- "additionalProperties": false,
+ "additionalProperties": true,
"x-note": "Select one option from the dropdown menu. Only one choice is allowed."
},
"tagGroup": {
From d5e5a692327ddc649fb1c67dfc2963395a39adc0 Mon Sep 17 00:00:00 2001
From: Nathan Bogale
Date: Mon, 30 Dec 2024 21:47:44 +0300
Subject: [PATCH 20/25] Fix: converted all html formatted content to markdown
---
...38-9258-4fbc-a62e-7faa6e58318f.schema.json | 273 ++++++------------
.../F14-Generic/example.proposal.json | 19 +-
2 files changed, 99 insertions(+), 193 deletions(-)
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
index afa71e375b5..746d52f9f0c 100644
--- a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
+++ b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
@@ -122,7 +122,7 @@
"type": "object",
"format": "singleGroupedTagSelector",
"additionalProperties": true,
- "x-note": "Select one option from the dropdown menu. Only one choice is allowed."
+ "x-note": "Select one option from the dropdown menu. Only one choice is allowed."
},
"tagGroup": {
"$comment": "UI - An individual group within a singleGroupedTagSelector.",
@@ -195,10 +195,10 @@
"title": {
"$ref": "#/definitions/singleLineTextEntry",
"title": "Proposal Title",
- "description": "Proposal title
Please note we suggest you use no more than 60 characters for your proposal title so that it can be easily viewed in the voting app.
",
+ "description": "**Proposal title**\n\nPlease note we suggest you use no more than 60 characters for your proposal title so that it can be easily viewed in the voting app.",
"minLength": 1,
"maxLength": 60,
- "x-guidance": "The title should clearly express what the proposal is about. Voters can see the title in the voting app, even without opening the proposal, so a clear, unambiguous, and concise title is very important.
"
+ "x-guidance": "The title should clearly express what the proposal is about. Voters can see the title in the voting app, even without opening the proposal, so a clear, unambiguous, and concise title is very important."
}
},
"required": [
@@ -212,7 +212,7 @@
"$ref": "#/definitions/singleLineTextEntry",
"title": "Name and surname of main applicant",
"description": "Name and surname of main applicant",
- "x-guidance": "Please provide the name and surname of the main applicant. The main applicant is considered as the individual responsible for the project and the person authorized to act on behalf of other applicants (where applicable).
",
+ "x-guidance": "Please provide the name and surname of the main applicant. The main applicant is considered as the individual responsible for the project and the person authorized to act on behalf of other applicants (where applicable).",
"minLength": 2,
"maxLength": 100
},
@@ -220,7 +220,7 @@
"$ref": "#/definitions/dropDownSingleSelect",
"title": "Are you delivering this project as an individual or as an entity (whether formally incorporated or not)",
"description": "Are you delivering this project as an individual or as an entity (whether formally incorporated or not)",
- "x-guidance": "Please select from one of the following:
- Individual
- Entity (Incorporated)
- Entity (Not Incorporated)
",
+ "x-guidance": "Please select from one of the following:\n\n1. Individual\n2. Entity (Incorporated)\n3. Entity (Not Incorporated)",
"enum": [
"Individual",
"Entity (Incorporated)",
@@ -232,7 +232,7 @@
"$ref": "#/definitions/singleLineTextEntryList",
"title": "Co-proposers and additional applicants",
"description": "Co-proposers and additional applicants",
- "x-guidance": "List any persons who are submitting the proposal jointly with the main applicant. Make sure you have confirmed approval/awareness with these individuals/accounts before adding them. If there is more than one proposer, identify the lead person who is authorized to act on behalf of other co-proposers. IMPORTANT A maximum of 6 (six) proposals can be led or co-proposed by the same applicant or enterprise. Please, reference Fund 14 rules for added detail.
",
+ "x-guidance": "List any persons who are submitting the proposal jointly with the main applicant. Make sure you have confirmed approval/awareness with these individuals/accounts before adding them. If there is more than one proposer, identify the lead person who is authorized to act on behalf of other co-proposers. **IMPORTANT** A maximum of 6 (six) proposals can be led or co-proposed by the same applicant or enterprise. Please, reference Fund 14 rules for added detail.",
"maxItems": 5,
"minItems": 0
}
@@ -263,7 +263,7 @@
"$ref": "#/definitions/tokenValueCardanoADA",
"title": "Requested funds in ADA",
"description": "The amount of funding requested for your proposal",
- "x-guidance": "There is a minimum and a maximum amount of funding that can be requested in a single Catalyst proposal. These are outlined below per each category:
Minimum Funding Amount per proposal:
Cardano Open: A15,000
Cardano Uses Cases: A15,000
Cardano Partners: A500,000
Maximum Funding Amount per proposal:
Cardano Open:
- Developers (technical): A200,000
- Ecosystem (non-technical): A100,000
Cardano Uses Cases:
- Concept A150,000
- Product: A500,000
Cardano Partners:
- Enterprise R&D A2,000,000
- Growth & Acceleration: A2,000,000
",
+ "x-guidance": "There is a minimum and a maximum amount of funding that can be requested in a single Catalyst proposal. These are outlined below per each category:\n\nMinimum Funding Amount per proposal:\n\nCardano Open: A15,000\nCardano Uses Cases: A15,000\nCardano Partners: A500,000\n\nMaximum Funding Amount per proposal:\n\nCardano Open:\n- Developers (technical): A200,000\n- Ecosystem (non-technical): A100,000\n\nCardano Uses Cases:\n- Concept A150,000\n- Product: A500,000\n\nCardano Partners:\n- Enterprise R&D A2,000,000\n- Growth & Acceleration: A2,000,000",
"minimum": 15000,
"maximum": 2000000
}
@@ -280,7 +280,7 @@
"$ref": "#/definitions/durationInMonths",
"title": "Project Duration in Months",
"description": "Specify the expected duration of your project. Projects must be completable within 2-12 months.",
- "x-guidance": "Minimum 2 months-Maximum 12 months. The scope of your funding request and this project is expected to produce the deliverables you specify in the proposal within 2-12 months If you believe your project will take longer than 12 months, consider reducing the project's scope so that it becomes achievable within 12 months If your project completes earlier than scheduled so long as you have submitted your PoAs and Project Close-out report and video then your project can be closed out.
",
+ "x-guidance": "Minimum 2 months-Maximum 12 months. The scope of your funding request and this project is expected to produce the deliverables you specify in the proposal within 2-12 months. If you believe your project will take longer than 12 months, consider reducing the project's scope so that it becomes achievable within 12 months. If your project completes earlier than scheduled so long as you have submitted your PoAs and Project Close-out report and video then your project can be closed out.",
"minimum": 2,
"maximum": 12
}
@@ -298,7 +298,7 @@
"$ref": "#/definitions/yesNoChoice",
"title": "Auto-translated Status",
"description": "Indicate if your proposal has been auto-translated into English from another language",
- "x-guidance": "Tick YES if your proposal has been auto-translated into English from another language so readers are reminded that your proposal has been translated, and that they should be tolerant of any language imperfections. Tick NO if your proposal has not been auto-translated into English from another language
"
+ "x-guidance": "Tick YES if your proposal has been auto-translated into English from another language so readers are reminded that your proposal has been translated, and that they should be tolerant of any language imperfections. Tick NO if your proposal has not been auto-translated into English from another language"
},
"originalLanguage": {
"$ref": "#/definitions/singleLineTextEntry",
@@ -366,7 +366,7 @@
"description": "Clearly define the problem you aim to solve. This will be visible in the Catalyst voting app.",
"minLength": 10,
"maxLength": 200,
- "x-guidance": "Ensure you present a well-defined problem. What is the core issue that you hope to fix? Remember: the reader might not recognize the problem unless you state it clearly. This answer will be displayed on the Catalyst voting app, so voters will see it even if they don't open your proposal to read it in detail.
"
+ "x-guidance": "Ensure you present a well-defined problem. What is the core issue that you hope to fix? Remember: the reader might not recognize the problem unless you state it clearly. This answer will be displayed on the Catalyst voting app, so voters will see it even if they don't open your proposal to read it in detail."
},
"impact": {
"$ref": "#/definitions/multiSelect",
@@ -407,7 +407,7 @@
"description": "Briefly describe your solution. Focus on what you will do or create to solve the problem.",
"minLength": 10,
"maxLength": 200,
- "x-guidance": "Focus on what you are going to do, or make, or change, to solve the problem. So not 'There should be a way to....' but 'We will make a Clearly state how the solution addresses the specific problem you have identified - connect the 'why' and the 'how' This answer will be displayed on the Catalyst voting app, so voters will see it even if they do not open your proposal and read it in detail.
"
+ "x-guidance": "Focus on what you are going to do, or make, or change, to solve the problem. So not 'There should be a way to....' but 'We will make a...' Clearly state how the solution addresses the specific problem you have identified - connect the 'why' and the 'how'. This answer will be displayed on the Catalyst voting app, so voters will see it even if they do not open your proposal and read it in detail."
},
"approach": {
"$ref": "#/definitions/multiLineTextEntry",
@@ -432,107 +432,19 @@
"$ref": "#/definitions/section",
"title": "Supporting Documentation",
"description": "Additional resources and documentation for your proposal",
- "x-guidance": "Here, provide links to yours or your partner organization's website, repository, or marketing. Alternatively, provide links to any whitepaper or other publication relevant to your proposal. Note however that this is extra information that voters and Community Reviewers might choose not to read. You should not fail to include any of the questions in this form because you feel the answers can be found elsewhere. If any links are specified make sure these are added in good order (first link must be present before specifying second). Also ensure all links include https. Without these steps, the form will not be submittable and show errors
",
- "properties": {
- "mainRepository": {
- "$ref": "#/definitions/singleLineHttpsURLEntry",
- "title": "Main Code Repository",
- "description": "Primary repository where the project's code will be hosted"
- },
- "documentation": {
- "$ref": "#/definitions/singleLineHttpsURLEntry",
- "title": "Documentation URL",
- "description": "Main documentation site or resource for the project"
- },
- "other": {
- "$ref": "#/definitions/singleLineHttpsURLEntryList",
- "title": "Resource Links",
- "description": "Links to any other relevant documentation, code repositories, or marketing materials. All links must use HTTPS.",
- "minItems": 0,
- "maxItems": 5
- }
- }
+ "x-guidance": "Here, provide links to yours or your partner organization's website, repository, or marketing. Alternatively, provide links to any whitepaper or other publication relevant to your proposal. Note however that this is extra information that voters and Community Reviewers might choose not to read. You should not fail to include any of the questions in this form because you feel the answers can be found elsewhere. If any links are specified make sure these are added in good order (first link must be present before specifying second). Also ensure all links include https. Without these steps, the form will not be submittable and show errors"
},
"dependencies": {
"$ref": "#/definitions/section",
"title": "Project Dependencies",
"description": "External dependencies and requirements for project success",
- "x-guidance": "If your project has any dependencies and prerequisites for your project's success, list them here. These are usually external factors (such as third-party suppliers, external resources, third-party software, etc.) that may cause a delay, since a project has less control over them. In case of third party software, indicate whether you have the necessary licenses and permission to use such software.
",
- "properties": {
- "details": {
- "$ref": "#/definitions/nestedQuestionsList",
- "title": "Dependency Details",
- "description": "List and describe each dependency",
- "items": {
- "$ref": "#/definitions/nestedQuestions",
- "properties": {
- "name": {
- "$ref": "#/definitions/singleLineTextEntry",
- "title": "Dependency Name",
- "description": "Name of the organization, technology, or resource",
- "maxLength": 100
- },
- "type": {
- "$ref": "#/definitions/dropDownSingleSelect",
- "title": "Dependency Type",
- "description": "Type of dependency",
- "enum": [
- "Technical",
- "Organizational",
- "Legal",
- "Financial",
- "Other"
- ]
- },
- "description": {
- "$ref": "#/definitions/multiLineTextEntry",
- "title": "Description",
- "description": "Explain why this dependency is essential and how it affects your project",
- "maxLength": 500
- },
- "mitigationPlan": {
- "$ref": "#/definitions/multiLineTextEntry",
- "title": "Mitigation Plan",
- "description": "How will you handle potential issues with this dependency",
- "maxLength": 300
- }
- },
- "required": [
- "name",
- "type",
- "description"
- ]
- },
- "minItems": 0,
- "maxItems": 10
- }
- }
+ "x-guidance": "If your project has any dependencies and prerequisites for your project's success, list them here. These are usually external factors (such as third-party suppliers, external resources, third-party software, etc.) that may cause a delay, since a project has less control over them. In case of third party software, indicate whether you have the necessary licenses and permission to use such software."
},
"open_source": {
"$ref": "#/definitions/section",
"title": "Project Open Source",
"description": "Will your project's output be fully open source? Open source refers to something people can modify and share because its design is publicly accessible.",
- "x-guidance": "Open source software is software with source code that anyone can inspect, modify, and enhance. Conversely, only the original authors of proprietary software can legally copy, inspect, and alter that software
",
- "properties": {
- "source_code": {
- "$ref": "#/definitions/spdxLicenseOrURL"
- },
- "documentation": {
- "$ref": "#/definitions/spdxLicenseOrURL"
- },
- "note": {
- "$ref": "#/definitions/multiLineTextEntry",
- "title": "More Information",
- "description": "Please provide here more information on the open source status of your project outputs",
- "maxLength": 500,
- "x-guidance": "If you did not answer PROPRIETARY to the above questions, the project should be open source available throughout the entire lifecycle of the project with a declared open-source repository. Please indicate here the type of license you intend to use for open source and provide any further information you feel is relevant to the open source status of your project outputs If only certain elements of your code will be open source please clarify which elements will be open source here. If you answered NO to the above question, please give further details as to why your projects outputs will not be open source METADATA
"
- }
- },
- "required": [
- "source_code",
- "documentation"
- ],
- "x-order": ["source_code", "documentation", "note"]
+ "x-guidance": "Open source software is software with source code that anyone can inspect, modify, and enhance. Conversely, only the original authors of proprietary software can legally copy, inspect, and alter that software"
}
},
"x-order": [
@@ -557,8 +469,7 @@
"properties": {
"grouped_tag": {
"$ref": "#/definitions/singleGroupedTagSelector",
- "oneOf": [
- {
+ "oneOf": [{
"properties": {
"group": {
"$ref": "#/definitions/tagGroup",
@@ -813,22 +724,20 @@
"solution": {
"$ref": "#/definitions/section",
"title": "Solution",
- "description": "How you write this section will depend on what type of proposal you are writing. You might want to include details on:
- How do you perceive the problem you are solving?
- What are your reasons for approaching it in the way that you have?
- Who will your project engage?
- How will you demonstrate or prove your impact?
Explain what is unique about your solution, who will benefit, and why this is important to Cardano.
",
+ "description": "How you write this section will depend on what type of proposal you are writing. You might want to include details on:\n\n- How do you perceive the problem you are solving?\n- What are your reasons for approaching it in the way that you have?\n- Who will your project engage?\n- How will you demonstrate or prove your impact?\n\nExplain what is unique about your solution, who will benefit, and why this is important to Cardano.",
"properties": {
"solution": {
"$ref": "#/definitions/multiLineTextEntryMarkdown",
"minLength": 1,
"maxLength": 10240,
- "examples": [
- "Our solution involves developing a decentralized education platform that will..."
- ]
+ "x-guidance": "Our solution involves developing a decentralized education platform that will..."
}
}
},
"impact": {
"$ref": "#/definitions/section",
"title": "Impact",
- "description": "Please include here a description of how you intend to measure impact (whether quantitative or qualitative) and how and with whom you will share your outputs:
- In what way will the success of your project bring value to the Cardano Community?
- How will you measure this impact?
- How will you share the outputs and opportunities that result from your project?
",
+ "description": "Please include here a description of how you intend to measure impact (whether quantitative or qualitative) and how and with whom you will share your outputs:\n\n- In what way will the success of your project bring value to the Cardano Community?\n- How will you measure this impact?\n- How will you share the outputs and opportunities that result from your project?",
"properties": {
"impact": {
"$ref": "#/definitions/multiLineTextEntryMarkdown",
@@ -840,7 +749,7 @@
"feasibility": {
"$ref": "#/definitions/section",
"title": "Capabilities & Feasibility",
- "description": "Please describe your existing capabilities that demonstrate how and why you believe you’re best suited to deliver this project?
Please include the steps or processes that demonstrate that you can be trusted to manage funds properly.
",
+ "description": "Please describe your existing capabilities that demonstrate how and why you believe you're best suited to deliver this project?\n\nPlease include the steps or processes that demonstrate that you can be trusted to manage funds properly.",
"properties": {
"feasibility": {
"$ref": "#/definitions/multiLineTextEntryMarkdown",
@@ -852,78 +761,78 @@
},
"x-order": ["solution", "impact", "feasibility"]
},
-"milestones": {
- "$ref": "#/definitions/segment",
- "title": "Milestones",
- "properties": {
"milestones": {
- "$ref": "#/definitions/section",
- "title": "Project Milestones",
- "description": "Each milestone must declare:
- A: Milestone outputs
- B: Acceptance criteria
- C: Evidence of completion
Requirements:
- For Grant Amounts up to 75k ada: minimum 3 milestones (2 + final)
- For Grant Amounts 75k-150k ada: minimum 4 milestones (3 + final)
- The final milestone must include Project Close-out Report and Video
",
+ "$ref": "#/definitions/segment",
+ "title": "Milestones",
"properties": {
- "milestone_list": {
- "type": "array",
- "title": "Milestones",
- "description": "What are the key milestones you need to achieve in order to complete your project successfully?",
- "x-guidance": "Milestone Requirements:
- For Grant Amounts of up to 75k ada: at least 2 milestones, plus the final one including Project Close-out Report and Video, must be included (3 milestones in total)
- For Grant Amounts over 75k ada up to 150k ada: at least 3 milestones, plus the final one including Project Close-out Report and Video, must be included (4 milestones in total)
- For Grant Amounts over 150k ada up to 300k ada: at least 4 milestones, plus the final one including Project Close-out Report and Video, must be included (5 milestones in total)
- For Grant Amounts exceeding 300k ada: at least 5 milestones, plus the final one including Project Close-out Report and Video, must be included (6 milestones in total)
",
- "minItems": 3,
- "maxItems": 6,
- "items": {
- "type": "object",
- "required": ["title", "outputs", "acceptance_criteria", "evidence", "delivery_month", "cost"],
- "properties": {
- "title": {
- "$ref": "#/definitions/singleLineTextEntry",
- "title": "Milestone Title",
- "description": "A clear, concise title for this milestone",
- "maxLength": 100
- },
- "outputs": {
- "$ref": "#/definitions/multiLineTextEntryMarkdown",
- "title": "Milestone Outputs",
- "description": "What will be delivered in this milestone",
- "maxLength": 1000
- },
- "acceptance_criteria": {
- "$ref": "#/definitions/multiLineTextEntryMarkdown",
- "title": "Acceptance Criteria",
- "description": "Specific conditions that must be met",
- "maxLength": 1000
- },
- "evidence": {
- "$ref": "#/definitions/multiLineTextEntryMarkdown",
- "title": "Evidence of Completion",
- "description": "How you will demonstrate achievement",
- "maxLength": 1000
- },
- "delivery_month": {
- "$ref": "#/definitions/durationInMonths",
- "title": "Delivery Month",
- "description": "The month when this milestone will be delivered",
- "minimum": 1,
- "maximum": 12
- },
- "cost": {
- "$ref": "#/definitions/tokenValueCardanoADA",
- "title": "Cost in ADA",
- "description": "The cost of this milestone in ADA"
- },
- "progress": {
- "$ref": "#/definitions/dropDownSingleSelect",
- "title": "Progress Status",
- "description": "Current status of the milestone",
- "enum": ["Not Started", "In Progress", "Completed", "Delayed"],
- "default": "Not Started"
+ "milestones": {
+ "$ref": "#/definitions/section",
+ "title": "Project Milestones",
+ "description": "Each milestone must declare:\n\n- A: Milestone outputs\n- B: Acceptance criteria\n- C: Evidence of completion\n\n**Requirements:**\n\n- For Grant Amounts up to 75k ada: minimum 3 milestones (2 + final)\n- For Grant Amounts 75k-150k ada: minimum 4 milestones (3 + final)\n- The final milestone must include Project Close-out Report and Video",
+ "properties": {
+ "milestone_list": {
+ "type": "array",
+ "title": "Milestones",
+ "description": "What are the key milestones you need to achieve in order to complete your project successfully?",
+ "x-guidance": "**Milestone Requirements:**\n\n- For Grant Amounts of up to 75k ada: at least 2 milestones, plus the final one including Project Close-out Report and Video, must be included (**3 milestones in total**)\n- For Grant Amounts over 75k ada up to 150k ada: at least 3 milestones, plus the final one including Project Close-out Report and Video, must be included (**4 milestones in total**)\n- For Grant Amounts over 150k ada up to 300k ada: at least 4 milestones, plus the final one including Project Close-out Report and Video, must be included (**5 milestones in total**)\n- For Grant Amounts exceeding 300k ada: at least 5 milestones, plus the final one including Project Close-out Report and Video, must be included (**6 milestones in total**)",
+ "minItems": 3,
+ "maxItems": 6,
+ "items": {
+ "type": "object",
+ "required": ["title", "outputs", "acceptance_criteria", "evidence", "delivery_month", "cost"],
+ "properties": {
+ "title": {
+ "$ref": "#/definitions/singleLineTextEntry",
+ "title": "Milestone Title",
+ "description": "A clear, concise title for this milestone",
+ "maxLength": 100
+ },
+ "outputs": {
+ "$ref": "#/definitions/multiLineTextEntryMarkdown",
+ "title": "Milestone Outputs",
+ "description": "What will be delivered in this milestone",
+ "maxLength": 1000
+ },
+ "acceptance_criteria": {
+ "$ref": "#/definitions/multiLineTextEntryMarkdown",
+ "title": "Acceptance Criteria",
+ "description": "Specific conditions that must be met",
+ "maxLength": 1000
+ },
+ "evidence": {
+ "$ref": "#/definitions/multiLineTextEntryMarkdown",
+ "title": "Evidence of Completion",
+ "description": "How you will demonstrate achievement",
+ "maxLength": 1000
+ },
+ "delivery_month": {
+ "$ref": "#/definitions/durationInMonths",
+ "title": "Delivery Month",
+ "description": "The month when this milestone will be delivered",
+ "minimum": 1,
+ "maximum": 12
+ },
+ "cost": {
+ "$ref": "#/definitions/tokenValueCardanoADA",
+ "title": "Cost in ADA",
+ "description": "The cost of this milestone in ADA"
+ },
+ "progress": {
+ "$ref": "#/definitions/dropDownSingleSelect",
+ "title": "Progress Status",
+ "description": "Current status of the milestone",
+ "enum": ["Not Started", "In Progress", "Completed", "Delayed"],
+ "default": "Not Started"
+ }
+ }
}
}
- }
+ },
+ "required": ["milestone_list"]
}
},
- "required": ["milestone_list"]
- }
- },
- "x-order": ["milestones"]
-},
+ "x-order": ["milestones"]
+ },
"pitch": {
"$ref": "#/definitions/segment",
"title": "Final Pitch",
@@ -935,7 +844,7 @@
"who": {
"$ref": "#/definitions/multiLineTextEntryMarkdown",
"title": "Who is in the project team and what are their roles?",
- "description": "List your team, their Linkedin profiles (or similar) and state what aspect of the proposal’s work each team member will undertake.
If you are planning to recruit additional team members, please state what specific skills you will be looking for in the people you recruit, so readers can see that you understand what skills will be needed to complete the project.
You are expected to have already engaged the relevant members of the organizations referenced so you understand if they are willing and/or have capacity to support the project. If you have not taken any steps to engage with your team yet, it is likely that the resources will not be available if you are approved for funding, which can jeopardize the project before it has even begun. The Catalyst team cannot help with this, meaning you are expected to have understood the requirements and engaged the necessary people before submitting a proposal.
Have you engaged anyone on any of the technical group channels (eg Discord or Telegram), or do you have a direct line of communications with the people and resources required?
Important: Catalyst funding is not anonymous, and some level of ‘proof of life’ verifications will take place before initial funding is released. Also remember that your proposal will be publicly available, so make sure to obtain any consent required before including confidential or third party information.
All Project Participants must disclose their role and scope of services across any submitted proposals, even if they are not in the lead or co-proposer role, such as an implementer, vendor, service provider, etc. Failure to disclose this information may lead to disqualification from the current grant round.
",
+ "description": "List your team, their Linkedin profiles (or similar) and state what aspect of the proposal's work each team member will undertake.\n\nIf you are planning to recruit additional team members, please state what specific skills you will be looking for in the people you recruit, so readers can see that you understand what skills will be needed to complete the project.\n\nYou are expected to have already engaged the relevant members of the organizations referenced so you understand if they are willing and/or have capacity to support the project. If you have not taken any steps to engage with your team yet, it is likely that the resources will not be available if you are approved for funding, which can jeopardize the project before it has even begun. The Catalyst team cannot help with this, meaning you are expected to have understood the requirements and engaged the necessary people before submitting a proposal.\n\nHave you engaged anyone on any of the technical group channels (eg Discord or Telegram), or do you have a direct line of communications with the people and resources required?\n\nImportant: Catalyst funding is not anonymous, and some level of 'proof of life' verifications will take place before initial funding is released. Also remember that your proposal will be publicly available, so make sure to obtain any consent required before including confidential or third party information.\n\nAll Project Participants must disclose their role and scope of services across any submitted proposals, even if they are not in the lead or co-proposer role, such as an implementer, vendor, service provider, etc. Failure to disclose this information may lead to disqualification from the current grant round.",
"minLength": 1,
"maxLength": 10240
}
@@ -948,7 +857,7 @@
"costs": {
"$ref": "#/definitions/multiLineTextEntryMarkdown",
"title": "Please provide a cost breakdown of the proposed work and resources",
- "description": "Make sure every element mentioned in your plan reflects its cost. It may be helpful to refer to your plan and timeline, list all the resources you will need at each stage, and what they cost.
Here, provide a clear description of any third party product or service you will be using. This could be hardware, software licenses, professional services (legal, accounting, code auditing, etc) but does not need to include the use of contracted programmers and developers.
The exact budget elements you include will depend on what type of work you are doing, and you might need to give less detail for a small, low-budget proposal. If the cost of the project will exceed the funding request, please provide information about alternative sources of funding.
Consider including budget elements for publicity / marketing / promotion / community engagement; project management; documentation; and reporting back to the community. Most proposals need these, but many proposers forget to include them.
It is the project team’s responsibility to properly manage the funds provided. Make sure to reference Fund Rules to understand eligibility around costs.
",
+ "description": "Make sure every element mentioned in your plan reflects its cost. It may be helpful to refer to your plan and timeline, list all the resources you will need at each stage, and what they cost.\n\nHere, provide a clear description of any third party product or service you will be using. This could be hardware, software licenses, professional services (legal, accounting, code auditing, etc) but does not need to include the use of contracted programmers and developers.\n\nThe exact budget elements you include will depend on what type of work you are doing, and you might need to give less detail for a small, low-budget proposal. If the cost of the project will exceed the funding request, please provide information about alternative sources of funding.\n\nConsider including budget elements for publicity / marketing / promotion / community engagement; project management; documentation; and reporting back to the community. Most proposals need these, but many proposers forget to include them.\n\nIt is the project team's responsibility to properly manage the funds provided. Make sure to reference [Fund Rules](https://docs.projectcatalyst.io/current-fund/fund-basics/fund-rules) to understand eligibility around costs.",
"minLength": 1,
"maxLength": 10240
}
@@ -961,7 +870,7 @@
"note": {
"$ref": "#/definitions/multiLineTextEntryMarkdown",
"title": "How does the cost of the project represent value for money for the Cardano ecosystem?",
- "description": "Use the response to provide the context about the costs you listed previously, particularly if they are high.
It may be helpful to include some brief information on how you have decided on the costs of the project.
For instance, can you justify with supporting evidence that costs are proportional to the average wage in your country, or typical freelance rates in your industry? Is there anything else that helps to support how the project represents value for money?
",
+ "description": "Use the response to provide the context about the costs you listed previously, particularly if they are high.\n\nIt may be helpful to include some brief information on how you have decided on the costs of the project.\n\nFor instance, can you justify with supporting evidence that costs are proportional to the average wage in your country, or typical freelance rates in your industry? Is there anything else that helps to support how the project represents value for money?",
"minLength": 1,
"maxLength": 10240
}
@@ -981,17 +890,17 @@
"fund_rules": {
"$ref": "#/definitions/agreementConfirmation",
"title": "Fund Rules:",
- "description": "By submitting a proposal to Project Catalyst Fund14, I confirm that I have read and agree to be bound by the Fund Rules.
"
+ "description": "By submitting a proposal to Project Catalyst Fund14, I confirm that I have read and agree to be bound by the [Fund Rules](https://docs.projectcatalyst.io/current-fund/fund-basics/fund-rules)."
},
"terms_and_conditions": {
"$ref": "#/definitions/agreementConfirmation",
"title": "Terms and Conditions:",
- "description": "By submitting a proposal to Project Catalyst Fund14, I confirm that I have read and agree to be bound by the Project Catalyst Terms and Conditions.
"
+ "description": "By submitting a proposal to Project Catalyst Fund14, I confirm that I have read and agree to be bound by the [Project Catalyst Terms and Conditions](https://docs.projectcatalyst.io/current-fund/fund-basics/project-catalyst-terms-and-conditions)."
},
"privacy_policy": {
"$ref": "#/definitions/agreementConfirmation",
"title": "Privacy Policy: ",
- "description": "I acknowledge and agree that any data I share in connection with my participation in Project Catalyst Fund14 will be collected, stored, used and processed in accordance with the Catalyst FC’s Privacy Policy.
"
+ "description": "I acknowledge and agree that any data I share in connection with my participation in Project Catalyst Fund14 will be collected, stored, used and processed in accordance with the Catalyst FC's [Privacy Policy](https://docs.projectcatalyst.io/current-fund/fund-basics/project-catalyst-terms-and-conditions/catalyst-fc-privacy-policy)."
}
},
"required": [
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/example.proposal.json b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/example.proposal.json
index 01710279147..7aa31deb128 100644
--- a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/example.proposal.json
+++ b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/example.proposal.json
@@ -22,7 +22,7 @@
},
"translation": {
"isTranslated": true,
- "originalLanguage":"German",
+ "originalLanguage": "German",
"originalDocumentLink": "https://example.com/original-doc"
},
"problem": {
@@ -50,14 +50,12 @@
]
},
"dependencies": {
- "details": [
- {
- "name": "External API Service",
- "type": "Technical",
- "description": "Integration with third-party API service",
- "mitigationPlan": "Build fallback mechanisms and maintain alternative providers"
- }
- ]
+ "details": [{
+ "name": "External API Service",
+ "type": "Technical",
+ "description": "Integration with third-party API service",
+ "mitigationPlan": "Build fallback mechanisms and maintain alternative providers"
+ }]
},
"open_source": {
"source_code": "MIT",
@@ -86,8 +84,7 @@
},
"milestones": {
"milestones": {
- "milestone_list": [
- {
+ "milestone_list": [{
"title": "Initial Setup and Planning",
"outputs": "Project infrastructure setup and detailed planning documents",
"acceptance_criteria": "- Development environment configured\n- Detailed project plan approved",
From 04d1155a9be57d894247c0c253f2513c8439536d Mon Sep 17 00:00:00 2001
From: Nathan Bogale
Date: Mon, 30 Dec 2024 21:50:26 +0300
Subject: [PATCH 21/25] Fix: min and max stabilized in all topic
---
.../0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
index 746d52f9f0c..505f6445818 100644
--- a/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
+++ b/docs/src/architecture/08_concepts/document_templates/proposal/F14-Generic/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
@@ -304,6 +304,8 @@
"$ref": "#/definitions/singleLineTextEntry",
"title": "Original Language",
"description": "If auto-translated, specify the original language of your proposal",
+ "minLength": 2,
+ "maxLength": 50,
"enum": [
"Arabic",
"Chinese",
@@ -413,14 +415,19 @@
"$ref": "#/definitions/multiLineTextEntry",
"title": "Technical Approach",
"description": "Outline the technical approach or methodology you will use",
- "maxLength": 500
+ "maxLength": 500,
+ "minLength": 10
},
"innovationAspects": {
"$ref": "#/definitions/singleLineTextEntryList",
"title": "Innovation Aspects",
"description": "Key innovative aspects of your solution",
"minItems": 1,
- "maxItems": 5
+ "maxItems": 5,
+ "items": {
+ "maxLength": 200,
+ "minLength": 10
+ }
}
},
"required": [
From e20e2d5e920d5fc0dcb75430d2184b38ff4be88c Mon Sep 17 00:00:00 2001
From: nathanbogale
Date: Tue, 31 Dec 2024 15:21:51 +0300
Subject: [PATCH 22/25] fix: merge cleanup and alignment with main
---
.config/dictionaries/project.dic | 15 +-
.github/CODEOWNERS | 14 +-
catalyst-gateway/Earthfile | 16 +
catalyst-gateway/bin/Cargo.toml | 5 +-
catalyst-gateway/bin/src/db/event/mod.rs | 5 +-
.../bin/src/db/event/signed_docs/mod.rs | 32 +
.../sql/insert_signed_documents.sql | 12 +
.../bin/src/db/event/signed_docs/tests/mod.rs | 50 +
catalyst-gateway/bin/src/settings/mod.rs | 4 -
catalyst-gateway/blueprint.cue | 5 +
catalyst-gateway/docker-compose.yml | 12 +-
catalyst-gateway/event-db/Earthfile | 38 +-
catalyst-gateway/event-db/blueprint.cue | 9 +-
.../migrations/V2__signed_documents.sql | 8 +-
catalyst-gateway/event-db/poetry.lock | 311 ++++
catalyst-gateway/event-db/pyproject.toml | 23 +
.../queries/insert_signed_documents.sql | 22 +
.../queries/select_signed_documents.sql.jinja | 12 +
.../select_signed_documents_2.sql.jinja | 12 +
.../event-db/tests/docker-compose.yml | 30 +
.../tests/test_signed_docs_queries.py | 147 ++
catalyst_voices/.gitignore | 1 +
catalyst_voices/Earthfile | 20 +-
.../apps/voices/integration_test/Earthfile | 2 +-
.../voices/integration_test/all_test.dart | 17 +
.../voices/integration_test/app_test.dart | 137 +-
.../integration_test/onboarding_test.dart | 52 +
.../pageobject/app_bar_page.dart | 8 +
.../pageobject/common_page.dart | 10 +
.../pageobject/onboarding_page.dart | 159 ++
.../pageobject/overall_spaces_page.dart | 15 +
.../pageobject/spaces_drawer_page.dart | 159 ++
.../types/registration_state.dart | 15 +
.../utils/selector_utils.dart | 22 +
.../utils/translations_utils.dart | 8 +
.../apps/voices/lib/app/view/app.dart | 24 +-
.../app/view/app_active_state_listener.dart | 49 +
.../apps/voices/lib/app/view/app_content.dart | 13 +-
.../lib/common/codecs/markdown_codec.dart | 60 +
.../voices/lib/common/ext/guidance_ext.dart | 2 +-
.../apps/voices/lib/common/ext/map_ext.dart | 7 +
.../lib/common/ext/time_of_day_ext.dart | 10 +
.../lib/common/formatters/date_formatter.dart | 68 +
.../apps/voices/lib/configs/bootstrap.dart | 44 +-
.../voices/lib/dependency/dependencies.dart | 123 +-
.../pages/account/unlock_keychain_dialog.dart | 1 +
.../campaign_admin_tools_dialog.dart | 348 +++++
.../campaign_admin_tools_events.dart | 354 +++++
.../campaign_admin_tools_views.dart | 60 +
.../details/campaign_details_dialog.dart | 69 +
.../widgets/campaign_categories_tile.dart | 165 +++
.../widgets/campaign_details_tile.dart | 210 +++
.../details/widgets/campaign_header.dart | 22 +
.../details/widgets/campaign_management.dart | 137 ++
.../widgets/campaign_management_dialog.dart | 127 ++
.../widgets/campaign_sections_list_view.dart | 41 +
.../pages/discovery/current_status_text.dart | 10 +-
.../lib/pages/discovery/discovery_page.dart | 428 +++++-
.../pages/discovery/toggle_state_text.dart | 65 +-
.../funded_projects/funded_projects_page.dart | 8 +-
.../apps/voices/lib/pages/login/login.dart | 3 -
.../voices/lib/pages/login/login_button.dart | 34 -
.../pages/login/login_email_text_filed.dart | 30 -
.../voices/lib/pages/login/login_form.dart | 72 -
.../voices/lib/pages/login/login_page.dart | 13 -
.../login/login_password_text_field.dart | 38 -
.../space/treasury_overview.dart | 6 +-
.../spaces_overview_list_view.dart | 53 +-
.../proposal_builder/proposal_builder.dart | 1 +
.../proposal_builder_body.dart} | 8 +-
.../proposal_builder_guidance_view.dart} | 16 +-
.../proposal_builder_navigation_panel.dart} | 4 +-
.../proposal_builder_page.dart | 108 ++
.../proposal_builder_rich_text_step.dart} | 37 +-
.../proposal_builder_setup_panel.dart | 63 +
.../get_started/get_started_panel.dart | 4 +-
.../registration_details_panel.dart | 1 +
.../registration/registration_info_panel.dart | 1 +
.../widgets/information_panel.dart | 8 +-
.../widgets/registration_stage_message.dart | 2 +
.../pages/spaces/drawer/discovery_menu.dart | 5 +
.../lib/pages/spaces/drawer/guest_menu.dart | 1 +
.../drawer/individual_private_campaigns.dart | 1 +
.../spaces/drawer/my_private_proposals.dart | 26 +-
.../lib/pages/spaces/drawer/space_header.dart | 1 +
.../pages/spaces/drawer/spaces_drawer.dart | 40 +-
.../pages/spaces/drawer/voting_rounds.dart | 1 +
.../lib/pages/spaces/spaces_shell_page.dart | 192 ++-
.../treasury_campaign_categories_step.dart | 34 +
.../treasury_campaign_details_step.dart} | 8 +-
.../treasury_campaign_stages_edit_step.dart | 162 ++
.../treasury_campaign_stages_view_step.dart | 151 ++
.../steps/treasury_campaign_widgets.dart | 106 ++
.../treasury_proposal_template_step.dart | 34 +
.../lib/pages/treasury/treasury_body.dart | 35 +-
.../lib/pages/treasury/treasury_page.dart | 20 +-
.../voices/lib/pages/voting/voting_page.dart | 8 +-
.../lib/pages/workspace/rich_text/answer.dart | 5 -
.../workspace/rich_text/bonus_mark_up.dart | 78 -
.../delivery_and_accountability.dart | 53 -
.../rich_text/feasibility_checks.dart | 12 -
.../rich_text/problem_statement.dart | 8 -
.../rich_text/public_description.dart | 121 --
.../rich_text/solution_statement.dart | 8 -
.../lib/pages/workspace/rich_text/title.dart | 8 -
.../workspace/rich_text/value_for_money.dart | 16 -
.../workspace/workspace_empty_state.dart | 36 +
.../lib/pages/workspace/workspace_error.dart | 50 +
.../lib/pages/workspace/workspace_header.dart | 230 +++
.../pages/workspace/workspace_loading.dart | 39 +
.../lib/pages/workspace/workspace_page.dart | 171 +--
.../pages/workspace/workspace_proposals.dart | 79 +
.../workspace/workspace_setup_panel.dart | 100 --
.../apps/voices/lib/routes/app_router.dart | 3 +-
.../lib/routes/guards/user_access_guard.dart | 46 +
.../lib/routes/routing/login_route.dart | 15 -
.../routes/routing/overall_spaces_route.dart | 8 +-
.../voices/lib/routes/routing/routes.dart | 2 -
.../voices/lib/routes/routing/routing.dart | 1 -
.../lib/routes/routing/spaces_route.dart | 77 +-
.../session/session_action_header.dart | 1 +
.../lib/widgets/buttons/voices_buttons.dart | 2 +
.../widgets/cards/campaign_stage_card.dart | 126 ++
.../widgets/cards/funded_proposal_card.dart | 10 +-
.../lib/widgets/cards/guidance_card.dart | 14 +-
.../widgets/cards/pending_proposal_card.dart | 84 +-
.../lib/widgets/cards/proposal_card.dart | 56 +
.../lib/widgets/common/affix_decorator.dart | 7 +-
.../common/proposal_status_container.dart | 12 +-
.../containers/grey_out_container.dart | 23 +
.../containers/workspace_tile_container.dart | 2 +-
.../document_builder/document_property.dart | 34 +
.../lib/widgets/drawer/voices_drawer.dart | 4 +
.../drawer/voices_drawer_space_chooser.dart | 26 +-
.../lib/widgets/empty_state/empty_state.dart | 76 +
.../lib/widgets/headers/brand_header.dart | 1 +
.../lib/widgets/headers/segment_header.dart | 4 +-
.../widgets/images/voices_image_scheme.dart | 23 +
.../widgets/indicators/voices_indicator.dart | 2 +-
.../lib/widgets/menu/voices_modal_menu.dart | 179 +++
.../lib/widgets/menu/voices_node_menu.dart | 6 +-
.../details/voices_align_title_header.dart | 54 +
.../modals/details/voices_details_dialog.dart | 39 +
.../details/voices_details_dialog_header.dart | 161 ++
.../widgets/modals/voices_desktop_dialog.dart | 52 +-
.../modals/voices_upload_file_dialog.dart | 17 +-
.../navigation/sections_controller.dart | 38 +-
.../navigation/sections_list_view.dart | 62 +-
.../lib/widgets/navigation/sections_menu.dart | 4 +-
.../pickers/voices_calendar_picker.dart | 93 ++
.../widgets/pickers/voices_time_picker.dart | 141 ++
.../widgets/rich_text/voices_rich_text.dart | 10 +-
.../widgets/text_field/voices_date_field.dart | 223 +++
.../text_field/voices_date_time_field.dart | 328 ++++
.../voices_date_time_text_field.dart | 96 ++
.../voices_password_text_field.dart | 5 +
.../widgets/text_field/voices_text_field.dart | 87 +-
.../widgets/text_field/voices_time_field.dart | 175 +++
.../widgets/tiles/voices_expansion_tile.dart | 107 ++
.../lib/widgets/tiles/voices_nav_tile.dart | 1 +
.../toggles/voices_theme_mode_switch.dart | 1 +
.../apps/voices/lib/widgets/widgets.dart | 4 +
.../Flutter/GeneratedPluginRegistrant.swift | 2 +
catalyst_voices/apps/voices/pubspec.yaml | 6 +
.../common/codecs/markdown_codec_test.dart | 89 ++
.../cards/campaign_stage_card_test.dart | 154 ++
.../text_field/voices_text_field_test.dart | 4 +-
catalyst_voices/justfile | 7 +-
catalyst_voices/melos.yaml | 33 +-
.../assets/images/no_proposal_foreground.svg | 41 +
.../lib/src/admin_tools/admin_tools.dart | 2 +
.../src/admin_tools/admin_tools_cubit.dart | 35 +
.../src/admin_tools/admin_tools_state.dart | 30 +
.../src/authentication/authentication.dart | 1 -
.../authentication/authentication_bloc.dart | 67 -
.../authentication/authentication_event.dart | 13 -
.../authentication/authentication_state.dart | 28 -
.../campaign_builder/campaign_builder.dart | 1 +
.../campaign_builder_cubit.dart | 50 +
.../campaign_builder_state.dart | 32 +
.../campaign/details/campaign_details.dart | 3 +
.../details/campaign_details_bloc.dart | 56 +
.../details/campaign_details_event.dart | 16 +
.../details/campaign_details_state.dart | 29 +
.../lib/src/campaign/info/campaign_info.dart | 2 +
.../campaign/info/campaign_info_cubit.dart | 72 +
.../campaign/info/campaign_info_state.dart | 16 +
.../lib/src/catalyst_voices_blocs.dart | 9 +-
.../lib/src/login/login.dart | 1 -
.../lib/src/login/login_bloc.dart | 87 --
.../lib/src/login/login_event.dart | 30 -
.../lib/src/login/login_state.dart | 35 -
.../proposal_builder/proposal_builder.dart | 3 +
.../proposal_builder_bloc.dart | 117 ++
.../proposal_builder_event.dart | 40 +
.../proposal_builder_state.dart | 47 +
.../lib/src/proposals/proposals.dart | 2 +
.../lib/src/proposals/proposals_cubit.dart | 146 ++
.../lib/src/proposals/proposals_state.dart | 29 +
.../registration/cubits/recover_cubit.dart | 12 +-
.../lib/src/session/session_cubit.dart | 158 +-
.../lib/src/session/session_state.dart | 43 +
.../lib/src/workspace/workspace.dart | 3 +
.../lib/src/workspace/workspace_bloc.dart | 99 ++
.../lib/src/workspace/workspace_event.dart | 38 +
.../lib/src/workspace/workspace_state.dart | 60 +
.../catalyst_voices_blocs/pubspec.yaml | 2 +
.../admin_tools/admin_tools_cubit_test.dart | 54 +
.../info/campaign_info_cubit_test.dart | 112 ++
.../test/proposals/proposals_cubit_test.dart | 203 +++
.../test/session/session_cubit_test.dart | 127 +-
.../lib/l10n/intl_en.arb | 252 +++-
.../analysis_options.yaml | 2 +-
.../catalyst_voices_models/build.yaml | 6 +
.../lib/src/app_config.dart | 56 +
.../lib/src/auth/authentication_status.dart | 5 -
.../lib/src/campaign/campaign.dart | 67 +
.../lib/src/campaign/campaign_category.dart | 14 +
.../lib/src/campaign/campaign_publish.dart | 9 +
.../lib/src/campaign/campaign_section.dart | 24 +
.../lib/src/catalyst_voices_models.dart | 20 +-
.../lib/src/crypto/keychain_metadata.dart | 46 -
.../lib/src/document/document_json.dart | 1 -
.../document_builder/document_builder.dart | 82 +
.../document_definitions.dart | 567 +++++++
.../src/document_builder/document_schema.dart | 121 ++
.../lib/src/markdown_data.dart | 1 +
.../lib/src/proposal/funded_proposal.dart | 37 -
.../lib/src/proposal}/guidance.dart | 26 +-
.../lib/src/proposal/pending_proposal.dart | 43 -
.../lib/src/proposal/proposal.dart | 65 +
.../lib/src/proposal/proposal_section.dart | 78 +
.../lib/src/proposal/proposal_status.dart | 9 -
.../lib/src/proposal/proposal_template.dart | 15 +
.../lib/src/session_data.dart | 43 -
.../lib/src/user/account.dart | 74 +-
.../lib/src/user/user.dart | 47 +-
.../catalyst_voices_models/pubspec.yaml | 7 +-
.../test/crypto/keychain_metadata_test.dart | 52 -
.../catalyst_voices_repositories/README.md | 31 +
.../analysis_options.yaml | 2 +-
.../catalyst_voices_repositories/build.yaml | 26 +
.../lib/generated/api/client_index.dart | 2 +
.../lib/generated/api}/client_mapping.dart | 0
.../lib/src/api_models/overriden_models.dart | 100 ++
.../lib/src/authentication_repository.dart | 66 -
.../lib/src/campaign/campaign_repository.dart | 153 ++
.../lib/src/catalyst_voices_repositories.dart | 7 +-
.../lib/src/config/config_repository.dart | 23 +
.../src/credentials_storage_repository.dart | 51 -
.../lib/src/dto/app_config_dto.dart | 121 ++
.../lib/src/dto/document_builder_dto.dart | 227 +++
.../lib/src/dto/document_definitions_dto.dart | 928 ++++++++++++
.../lib/src/dto/document_schema_dto.dart | 353 +++++
.../lib/src/dto/user_dto.dart | 159 ++
.../lib/src/proposal/proposal_repository.dart | 102 ++
.../lib/src/user/user_repository.dart | 46 +
.../lib/src/user/user_storage.dart | 43 +
.../lib/src/utils/json_converters.dart | 33 +
.../openapi-filters.json | 0
.../openapi/vit.yaml | 1313 +++++++++++++++++
.../catalyst_voices_repositories/pubspec.yaml | 13 +-
...38-9258-4fbc-a62e-7faa6e58318f.schema.json | 1067 ++++++++++++++
.../test/assets/generic_proposal.json | 138 ++
.../test/helpers/read_json.dart | 10 +
.../document_builder_test.dart | 51 +
.../document_definitions_test.dart | 54 +
.../document_schema_test.dart | 60 +
.../catalyst_voices_services/README.md | 36 -
.../catalyst_voices_services/build.yaml | 15 -
.../catalyst_gateway/client_index.dart | 1 -
.../lib/src/campaign/campaign_service.dart | 36 +
.../lib/src/catalyst_voices_services.dart | 15 +-
.../lib/src/config/config_service.dart | 22 +
.../lib/src/keychain/keychain.dart | 17 -
.../src/keychain/keychain_transformers.dart | 43 -
.../lib/src/keychain/vault_keychain.dart | 130 --
.../lib/src/proposal/proposal_service.dart | 32 +
.../registration/registration_service.dart | 48 +-
.../registration_transaction_builder.dart | 62 +-
.../lib/src/storage/dummy_auth_storage.dart | 47 -
.../lib/src/user/user_service.dart | 228 +--
.../lib/src/user/user_storage.dart | 25 -
.../catalyst_voices_services/pubspec.yaml | 15 +-
.../test/src/user/user_service_test.dart | 123 +-
.../lib/src/cache/cache.dart | 16 +
.../lib/src/cache/local_tll_cache.dart | 92 ++
.../lib/src/cache/ttl_cache.dart | 19 +
.../lib/src/catalyst_voices_shared.dart | 24 +
.../lib/src/crypto/crypto_service.dart | 0
.../lib/src/crypto/key_derivation.dart | 0
.../lib/src/crypto/local_crypto_service.dart} | 14 +-
.../src/dependency/dependency_provider.dart | 26 +-
.../lib/src/document/document_manager.dart | 83 ++
.../src/document/document_manager_impl.dart | 129 ++
.../extension/document_list_sort_ext.dart | 13 +
.../extension/document_map_to_list_ext.dart | 28 +
.../lib/src/document/identifiable.dart | 3 +
.../lib/src/keychain/keychain.dart | 14 +
.../lib/src/keychain/keychain_provider.dart | 2 +-
.../src/keychain/keychain_transformers.dart | 84 ++
.../lib/src/keychain/vault_keychain.dart | 67 +
.../src/keychain/vault_keychain_provider.dart | 43 +-
.../lib/src/range/range.dart | 18 +
.../lib/src/storage/local_storage.dart | 62 +
.../lib/src/storage/memory_storage.dart | 37 +
.../lib/src/storage/secure_storage.dart | 18 +-
.../lib/src/storage/storage.dart | 0
.../lib/src/storage/storage_string_mixin.dart | 5 +-
.../storage/vault/secure_storage_vault.dart | 180 ++-
.../vault/secure_storage_vault_cache.dart | 49 +
.../lib/src/storage/vault/vault.dart | 6 +-
.../lib/src/utils/active_aware.dart | 11 +
.../lib/src/utils}/lockable.dart | 4 +
.../catalyst_voices_shared/pubspec.yaml | 15 +
.../test/src/cache/local_tll_cache_test.dart | 79 +
.../test/src/crypto/key_derivation_test.dart | 2 +-
.../crypto/local_crypto_service_test.dart} | 4 +-
.../src/document/document_manager_test.dart | 172 +++
.../keychain/keychain_transformers_test.dart | 18 +-
.../vault_keychain_provider_test.dart | 23 +-
.../src/keychain/vault_keychain_test.dart | 75 +-
.../test/src/storage/secure_storage_test.dart | 2 +-
.../storage/storage_string_mixin_test.dart | 4 +-
.../vault/secure_storage_vault_test.dart | 19 +-
.../src/authentication/access_control.dart | 93 ++
.../src/authentication/authentication.dart | 1 +
.../campaign/campaign_category_section.dart | 41 +
.../lib/src/campaign/campaign_info.dart | 67 +
.../lib/src/campaign/campaign_list_item.dart | 42 +
.../lib/src/campaign/campaign_stage.dart | 45 +
.../lib/src/catalyst_voices_view_models.dart | 12 +-
.../lib/src/menu/menu_item.dart | 31 +
.../lib/src/menu/popup_menu_item.dart | 32 +
.../src/navigation/sections_navigation.dart | 19 +-
.../src/proposal/guidance/guidance_type.dart | 11 -
.../lib/src/proposal/proposal_view_model.dart | 151 ++
.../lib/src/session/session_status.dart | 20 +
.../lib/src/treasury/campaign_setup.dart | 30 -
.../lib/src/treasury/treasury_sections.dart | 66 +-
.../workspace/capability_and_feasibility.dart | 51 -
.../lib/src/workspace/proposal_impact.dart | 41 -
.../lib/src/workspace/proposal_setup.dart | 27 -
.../lib/src/workspace/proposal_solution.dart | 73 -
.../lib/src/workspace/proposal_summary.dart | 58 -
.../workspace_proposal_list_item.dart | 14 +
.../lib/src/workspace/workspace_sections.dart | 42 +-
.../lib/src/workspace/workspace_tab_type.dart | 17 +
.../catalyst_voices_view_models/pubspec.yaml | 3 +
.../test/campaign/campaign_stage_test.dart | 69 +
.../wallet-automation/pages/homePage.ts | 3 +-
.../wallet-automation/pages/modal.ts | 45 +-
.../wallet-automation/pages/walletListPage.ts | 22 +-
.../wallet-automation/setup.ts | 3 +-
.../wallet-automation/tests/wallets.spec.ts | 67 +-
.../utils/extensionDownloader.ts | 35 +-
.../wallet-automation/utils/extensions.ts | 12 +
.../wallet-automation/utils/walletConfigs.ts | 171 ++-
.../utils/wallets/nufiUtils.ts | 43 +
.../utils/wallets/walletUtils.ts | 47 +-
.../utils/wallets/yoroiUtils.ts | 49 +
.../lib/src/rbac/auth_token.dart | 19 +-
.../lib/src/utils/cbor.dart | 3 +
.../lib/src/utils/uuid.dart | 14 +
.../pubspec.yaml | 2 +-
.../test/rbac/auth_token_test.dart | 13 +-
.../packages/libs/catalyst_cose/README.md | 89 +-
.../libs/catalyst_cose/example/main.dart | 89 +-
.../libs/catalyst_cose/lib/catalyst_cose.dart | 7 +-
.../catalyst_cose/lib/src/catalyst_cose.dart | 149 --
.../catalyst_cose/lib/src/cose_constants.dart | 98 ++
.../libs/catalyst_cose/lib/src/cose_sign.dart | 261 ++++
.../catalyst_cose/lib/src/cose_sign1.dart | 162 ++
.../lib/src/types/cose_headers.dart | 229 +++
.../lib/src/types/string_or_int.dart | 61 +
.../catalyst_cose/lib/src/types/uuid.dart | 74 +
.../lib/src/utils/cbor_utils.dart | 84 ++
.../packages/libs/catalyst_cose/pubspec.yaml | 3 +
.../test/catalyst_cose_test.dart | 157 --
.../catalyst_cose/test/cose_sign1_test.dart | 101 ++
.../catalyst_cose/test/cose_sign_test.dart | 117 ++
.../lib/examples/voices_menu_example.dart | 8 +-
.../lib/examples/voices_modals_example.dart | 3 -
.../voices_proposal_card_example.dart | 13 +-
.../examples/voices_text_field_example.dart | 36 +-
.../utilities/uikit_example/pubspec.yaml | 2 +
cspell.json | 1 +
.../signed_document_metadata/.pages | 3 -
.../signed_document_metadata/metadata.md | 296 ----
.../0009-uuid7-vs-ulid.md | 82 +
390 files changed, 20116 insertions(+), 3897 deletions(-)
create mode 100644 catalyst-gateway/bin/src/db/event/signed_docs/mod.rs
create mode 100644 catalyst-gateway/bin/src/db/event/signed_docs/sql/insert_signed_documents.sql
create mode 100644 catalyst-gateway/bin/src/db/event/signed_docs/tests/mod.rs
create mode 100644 catalyst-gateway/event-db/poetry.lock
create mode 100644 catalyst-gateway/event-db/pyproject.toml
create mode 100644 catalyst-gateway/event-db/queries/insert_signed_documents.sql
create mode 100644 catalyst-gateway/event-db/queries/select_signed_documents.sql.jinja
create mode 100644 catalyst-gateway/event-db/queries/select_signed_documents_2.sql.jinja
create mode 100644 catalyst-gateway/event-db/tests/docker-compose.yml
create mode 100644 catalyst-gateway/event-db/tests/test_signed_docs_queries.py
create mode 100644 catalyst_voices/apps/voices/integration_test/all_test.dart
create mode 100644 catalyst_voices/apps/voices/integration_test/onboarding_test.dart
create mode 100644 catalyst_voices/apps/voices/integration_test/pageobject/app_bar_page.dart
create mode 100644 catalyst_voices/apps/voices/integration_test/pageobject/common_page.dart
create mode 100644 catalyst_voices/apps/voices/integration_test/pageobject/onboarding_page.dart
create mode 100644 catalyst_voices/apps/voices/integration_test/pageobject/overall_spaces_page.dart
create mode 100644 catalyst_voices/apps/voices/integration_test/pageobject/spaces_drawer_page.dart
create mode 100644 catalyst_voices/apps/voices/integration_test/types/registration_state.dart
create mode 100644 catalyst_voices/apps/voices/integration_test/utils/selector_utils.dart
create mode 100644 catalyst_voices/apps/voices/integration_test/utils/translations_utils.dart
create mode 100644 catalyst_voices/apps/voices/lib/app/view/app_active_state_listener.dart
create mode 100644 catalyst_voices/apps/voices/lib/common/codecs/markdown_codec.dart
create mode 100644 catalyst_voices/apps/voices/lib/common/ext/map_ext.dart
create mode 100644 catalyst_voices/apps/voices/lib/common/ext/time_of_day_ext.dart
create mode 100644 catalyst_voices/apps/voices/lib/pages/campaign/admin_tools/campaign_admin_tools_dialog.dart
create mode 100644 catalyst_voices/apps/voices/lib/pages/campaign/admin_tools/campaign_admin_tools_events.dart
create mode 100644 catalyst_voices/apps/voices/lib/pages/campaign/admin_tools/campaign_admin_tools_views.dart
create mode 100644 catalyst_voices/apps/voices/lib/pages/campaign/details/campaign_details_dialog.dart
create mode 100644 catalyst_voices/apps/voices/lib/pages/campaign/details/widgets/campaign_categories_tile.dart
create mode 100644 catalyst_voices/apps/voices/lib/pages/campaign/details/widgets/campaign_details_tile.dart
create mode 100644 catalyst_voices/apps/voices/lib/pages/campaign/details/widgets/campaign_header.dart
create mode 100644 catalyst_voices/apps/voices/lib/pages/campaign/details/widgets/campaign_management.dart
create mode 100644 catalyst_voices/apps/voices/lib/pages/campaign/details/widgets/campaign_management_dialog.dart
create mode 100644 catalyst_voices/apps/voices/lib/pages/campaign/details/widgets/campaign_sections_list_view.dart
delete mode 100644 catalyst_voices/apps/voices/lib/pages/login/login.dart
delete mode 100644 catalyst_voices/apps/voices/lib/pages/login/login_button.dart
delete mode 100644 catalyst_voices/apps/voices/lib/pages/login/login_email_text_filed.dart
delete mode 100644 catalyst_voices/apps/voices/lib/pages/login/login_form.dart
delete mode 100644 catalyst_voices/apps/voices/lib/pages/login/login_page.dart
delete mode 100644 catalyst_voices/apps/voices/lib/pages/login/login_password_text_field.dart
create mode 100644 catalyst_voices/apps/voices/lib/pages/proposal_builder/proposal_builder.dart
rename catalyst_voices/apps/voices/lib/pages/{workspace/workspace_body.dart => proposal_builder/proposal_builder_body.dart} (79%)
rename catalyst_voices/apps/voices/lib/pages/{workspace/workspace_guidance_view.dart => proposal_builder/proposal_builder_guidance_view.dart} (82%)
rename catalyst_voices/apps/voices/lib/pages/{workspace/workspace_navigation_panel.dart => proposal_builder/proposal_builder_navigation_panel.dart} (84%)
create mode 100644 catalyst_voices/apps/voices/lib/pages/proposal_builder/proposal_builder_page.dart
rename catalyst_voices/apps/voices/lib/pages/{workspace/workspace_rich_text_step.dart => proposal_builder/proposal_builder_rich_text_step.dart} (69%)
create mode 100644 catalyst_voices/apps/voices/lib/pages/proposal_builder/proposal_builder_setup_panel.dart
create mode 100644 catalyst_voices/apps/voices/lib/pages/treasury/steps/treasury_campaign_categories_step.dart
rename catalyst_voices/apps/voices/lib/pages/treasury/{treasury_dummy_topic_step.dart => steps/treasury_campaign_details_step.dart} (83%)
create mode 100644 catalyst_voices/apps/voices/lib/pages/treasury/steps/treasury_campaign_stages_edit_step.dart
create mode 100644 catalyst_voices/apps/voices/lib/pages/treasury/steps/treasury_campaign_stages_view_step.dart
create mode 100644 catalyst_voices/apps/voices/lib/pages/treasury/steps/treasury_campaign_widgets.dart
create mode 100644 catalyst_voices/apps/voices/lib/pages/treasury/steps/treasury_proposal_template_step.dart
delete mode 100644 catalyst_voices/apps/voices/lib/pages/workspace/rich_text/answer.dart
delete mode 100644 catalyst_voices/apps/voices/lib/pages/workspace/rich_text/bonus_mark_up.dart
delete mode 100644 catalyst_voices/apps/voices/lib/pages/workspace/rich_text/delivery_and_accountability.dart
delete mode 100644 catalyst_voices/apps/voices/lib/pages/workspace/rich_text/feasibility_checks.dart
delete mode 100644 catalyst_voices/apps/voices/lib/pages/workspace/rich_text/problem_statement.dart
delete mode 100644 catalyst_voices/apps/voices/lib/pages/workspace/rich_text/public_description.dart
delete mode 100644 catalyst_voices/apps/voices/lib/pages/workspace/rich_text/solution_statement.dart
delete mode 100644 catalyst_voices/apps/voices/lib/pages/workspace/rich_text/title.dart
delete mode 100644 catalyst_voices/apps/voices/lib/pages/workspace/rich_text/value_for_money.dart
create mode 100644 catalyst_voices/apps/voices/lib/pages/workspace/workspace_empty_state.dart
create mode 100644 catalyst_voices/apps/voices/lib/pages/workspace/workspace_error.dart
create mode 100644 catalyst_voices/apps/voices/lib/pages/workspace/workspace_header.dart
create mode 100644 catalyst_voices/apps/voices/lib/pages/workspace/workspace_loading.dart
create mode 100644 catalyst_voices/apps/voices/lib/pages/workspace/workspace_proposals.dart
delete mode 100644 catalyst_voices/apps/voices/lib/pages/workspace/workspace_setup_panel.dart
create mode 100644 catalyst_voices/apps/voices/lib/routes/guards/user_access_guard.dart
delete mode 100644 catalyst_voices/apps/voices/lib/routes/routing/login_route.dart
create mode 100644 catalyst_voices/apps/voices/lib/widgets/cards/campaign_stage_card.dart
create mode 100644 catalyst_voices/apps/voices/lib/widgets/cards/proposal_card.dart
create mode 100644 catalyst_voices/apps/voices/lib/widgets/containers/grey_out_container.dart
create mode 100644 catalyst_voices/apps/voices/lib/widgets/document_builder/document_property.dart
create mode 100644 catalyst_voices/apps/voices/lib/widgets/empty_state/empty_state.dart
create mode 100644 catalyst_voices/apps/voices/lib/widgets/images/voices_image_scheme.dart
create mode 100644 catalyst_voices/apps/voices/lib/widgets/menu/voices_modal_menu.dart
create mode 100644 catalyst_voices/apps/voices/lib/widgets/modals/details/voices_align_title_header.dart
create mode 100644 catalyst_voices/apps/voices/lib/widgets/modals/details/voices_details_dialog.dart
create mode 100644 catalyst_voices/apps/voices/lib/widgets/modals/details/voices_details_dialog_header.dart
create mode 100644 catalyst_voices/apps/voices/lib/widgets/pickers/voices_calendar_picker.dart
create mode 100644 catalyst_voices/apps/voices/lib/widgets/pickers/voices_time_picker.dart
create mode 100644 catalyst_voices/apps/voices/lib/widgets/text_field/voices_date_field.dart
create mode 100644 catalyst_voices/apps/voices/lib/widgets/text_field/voices_date_time_field.dart
create mode 100644 catalyst_voices/apps/voices/lib/widgets/text_field/voices_date_time_text_field.dart
create mode 100644 catalyst_voices/apps/voices/lib/widgets/text_field/voices_time_field.dart
create mode 100644 catalyst_voices/apps/voices/lib/widgets/tiles/voices_expansion_tile.dart
create mode 100644 catalyst_voices/apps/voices/test/common/codecs/markdown_codec_test.dart
create mode 100644 catalyst_voices/apps/voices/test/widgets/cards/campaign_stage_card_test.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_assets/assets/images/no_proposal_foreground.svg
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_blocs/lib/src/admin_tools/admin_tools.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_blocs/lib/src/admin_tools/admin_tools_cubit.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_blocs/lib/src/admin_tools/admin_tools_state.dart
delete mode 100644 catalyst_voices/packages/internal/catalyst_voices_blocs/lib/src/authentication/authentication.dart
delete mode 100644 catalyst_voices/packages/internal/catalyst_voices_blocs/lib/src/authentication/authentication_bloc.dart
delete mode 100644 catalyst_voices/packages/internal/catalyst_voices_blocs/lib/src/authentication/authentication_event.dart
delete mode 100644 catalyst_voices/packages/internal/catalyst_voices_blocs/lib/src/authentication/authentication_state.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_blocs/lib/src/campaign/campaign_builder/campaign_builder.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_blocs/lib/src/campaign/campaign_builder/campaign_builder_cubit.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_blocs/lib/src/campaign/campaign_builder/campaign_builder_state.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_blocs/lib/src/campaign/details/campaign_details.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_blocs/lib/src/campaign/details/campaign_details_bloc.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_blocs/lib/src/campaign/details/campaign_details_event.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_blocs/lib/src/campaign/details/campaign_details_state.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_blocs/lib/src/campaign/info/campaign_info.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_blocs/lib/src/campaign/info/campaign_info_cubit.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_blocs/lib/src/campaign/info/campaign_info_state.dart
delete mode 100644 catalyst_voices/packages/internal/catalyst_voices_blocs/lib/src/login/login.dart
delete mode 100644 catalyst_voices/packages/internal/catalyst_voices_blocs/lib/src/login/login_bloc.dart
delete mode 100644 catalyst_voices/packages/internal/catalyst_voices_blocs/lib/src/login/login_event.dart
delete mode 100644 catalyst_voices/packages/internal/catalyst_voices_blocs/lib/src/login/login_state.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_blocs/lib/src/proposal_builder/proposal_builder.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_blocs/lib/src/proposal_builder/proposal_builder_bloc.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_blocs/lib/src/proposal_builder/proposal_builder_event.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_blocs/lib/src/proposal_builder/proposal_builder_state.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_blocs/lib/src/proposals/proposals.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_blocs/lib/src/proposals/proposals_cubit.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_blocs/lib/src/proposals/proposals_state.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_blocs/lib/src/workspace/workspace.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_blocs/lib/src/workspace/workspace_bloc.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_blocs/lib/src/workspace/workspace_event.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_blocs/lib/src/workspace/workspace_state.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_blocs/test/admin_tools/admin_tools_cubit_test.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_blocs/test/campaign/info/campaign_info_cubit_test.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_blocs/test/proposals/proposals_cubit_test.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_models/build.yaml
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_models/lib/src/app_config.dart
delete mode 100644 catalyst_voices/packages/internal/catalyst_voices_models/lib/src/auth/authentication_status.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_models/lib/src/campaign/campaign.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_models/lib/src/campaign/campaign_category.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_models/lib/src/campaign/campaign_publish.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_models/lib/src/campaign/campaign_section.dart
delete mode 100644 catalyst_voices/packages/internal/catalyst_voices_models/lib/src/crypto/keychain_metadata.dart
delete mode 100644 catalyst_voices/packages/internal/catalyst_voices_models/lib/src/document/document_json.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_models/lib/src/document_builder/document_builder.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_models/lib/src/document_builder/document_definitions.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_models/lib/src/document_builder/document_schema.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_models/lib/src/markdown_data.dart
delete mode 100644 catalyst_voices/packages/internal/catalyst_voices_models/lib/src/proposal/funded_proposal.dart
rename catalyst_voices/packages/internal/{catalyst_voices_view_models/lib/src/proposal/guidance => catalyst_voices_models/lib/src/proposal}/guidance.dart (71%)
delete mode 100644 catalyst_voices/packages/internal/catalyst_voices_models/lib/src/proposal/pending_proposal.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_models/lib/src/proposal/proposal.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_models/lib/src/proposal/proposal_section.dart
delete mode 100644 catalyst_voices/packages/internal/catalyst_voices_models/lib/src/proposal/proposal_status.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_models/lib/src/proposal/proposal_template.dart
delete mode 100644 catalyst_voices/packages/internal/catalyst_voices_models/lib/src/session_data.dart
delete mode 100644 catalyst_voices/packages/internal/catalyst_voices_models/test/crypto/keychain_metadata_test.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_repositories/build.yaml
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_repositories/lib/generated/api/client_index.dart
rename catalyst_voices/packages/internal/{catalyst_voices_services/lib/generated/catalyst_gateway => catalyst_voices_repositories/lib/generated/api}/client_mapping.dart (100%)
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_repositories/lib/src/api_models/overriden_models.dart
delete mode 100644 catalyst_voices/packages/internal/catalyst_voices_repositories/lib/src/authentication_repository.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_repositories/lib/src/campaign/campaign_repository.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_repositories/lib/src/config/config_repository.dart
delete mode 100644 catalyst_voices/packages/internal/catalyst_voices_repositories/lib/src/credentials_storage_repository.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_repositories/lib/src/dto/app_config_dto.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_repositories/lib/src/dto/document_builder_dto.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_repositories/lib/src/dto/document_definitions_dto.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_repositories/lib/src/dto/document_schema_dto.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_repositories/lib/src/dto/user_dto.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_repositories/lib/src/proposal/proposal_repository.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_repositories/lib/src/user/user_repository.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_repositories/lib/src/user/user_storage.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_repositories/lib/src/utils/json_converters.dart
rename catalyst_voices/packages/internal/{catalyst_voices_services => catalyst_voices_repositories}/openapi-filters.json (100%)
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_repositories/openapi/vit.yaml
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_repositories/test/assets/0ce8ab38-9258-4fbc-a62e-7faa6e58318f.schema.json
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_repositories/test/assets/generic_proposal.json
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_repositories/test/helpers/read_json.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_repositories/test/src/document_builder/document_builder_test.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_repositories/test/src/document_builder/document_definitions_test.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_repositories/test/src/document_builder/document_schema_test.dart
delete mode 100644 catalyst_voices/packages/internal/catalyst_voices_services/build.yaml
delete mode 100644 catalyst_voices/packages/internal/catalyst_voices_services/lib/generated/catalyst_gateway/client_index.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_services/lib/src/campaign/campaign_service.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_services/lib/src/config/config_service.dart
delete mode 100644 catalyst_voices/packages/internal/catalyst_voices_services/lib/src/keychain/keychain.dart
delete mode 100644 catalyst_voices/packages/internal/catalyst_voices_services/lib/src/keychain/keychain_transformers.dart
delete mode 100644 catalyst_voices/packages/internal/catalyst_voices_services/lib/src/keychain/vault_keychain.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_services/lib/src/proposal/proposal_service.dart
delete mode 100644 catalyst_voices/packages/internal/catalyst_voices_services/lib/src/storage/dummy_auth_storage.dart
delete mode 100644 catalyst_voices/packages/internal/catalyst_voices_services/lib/src/user/user_storage.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_shared/lib/src/cache/cache.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_shared/lib/src/cache/local_tll_cache.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_shared/lib/src/cache/ttl_cache.dart
rename catalyst_voices/packages/internal/{catalyst_voices_services => catalyst_voices_shared}/lib/src/crypto/crypto_service.dart (100%)
rename catalyst_voices/packages/internal/{catalyst_voices_services => catalyst_voices_shared}/lib/src/crypto/key_derivation.dart (100%)
rename catalyst_voices/packages/internal/{catalyst_voices_services/lib/src/crypto/vault_crypto_service.dart => catalyst_voices_shared/lib/src/crypto/local_crypto_service.dart} (92%)
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_shared/lib/src/document/document_manager.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_shared/lib/src/document/document_manager_impl.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_shared/lib/src/document/extension/document_list_sort_ext.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_shared/lib/src/document/extension/document_map_to_list_ext.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_shared/lib/src/document/identifiable.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_shared/lib/src/keychain/keychain.dart
rename catalyst_voices/packages/internal/{catalyst_voices_services => catalyst_voices_shared}/lib/src/keychain/keychain_provider.dart (72%)
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_shared/lib/src/keychain/keychain_transformers.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_shared/lib/src/keychain/vault_keychain.dart
rename catalyst_voices/packages/internal/{catalyst_voices_services => catalyst_voices_shared}/lib/src/keychain/vault_keychain_provider.dart (67%)
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_shared/lib/src/range/range.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_shared/lib/src/storage/local_storage.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_shared/lib/src/storage/memory_storage.dart
rename catalyst_voices/packages/internal/{catalyst_voices_services => catalyst_voices_shared}/lib/src/storage/secure_storage.dart (75%)
rename catalyst_voices/packages/internal/{catalyst_voices_services => catalyst_voices_shared}/lib/src/storage/storage.dart (100%)
rename catalyst_voices/packages/internal/{catalyst_voices_services => catalyst_voices_shared}/lib/src/storage/storage_string_mixin.dart (89%)
rename catalyst_voices/packages/internal/{catalyst_voices_services => catalyst_voices_shared}/lib/src/storage/vault/secure_storage_vault.dart (52%)
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_shared/lib/src/storage/vault/secure_storage_vault_cache.dart
rename catalyst_voices/packages/internal/{catalyst_voices_services => catalyst_voices_shared}/lib/src/storage/vault/vault.dart (64%)
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_shared/lib/src/utils/active_aware.dart
rename catalyst_voices/packages/internal/{catalyst_voices_services/lib/src => catalyst_voices_shared/lib/src/utils}/lockable.dart (83%)
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_shared/test/src/cache/local_tll_cache_test.dart
rename catalyst_voices/packages/internal/{catalyst_voices_services => catalyst_voices_shared}/test/src/crypto/key_derivation_test.dart (97%)
rename catalyst_voices/packages/internal/{catalyst_voices_services/test/src/crypto/vault_crypto_service_test.dart => catalyst_voices_shared/test/src/crypto/local_crypto_service_test.dart} (96%)
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_shared/test/src/document/document_manager_test.dart
rename catalyst_voices/packages/internal/{catalyst_voices_services => catalyst_voices_shared}/test/src/keychain/keychain_transformers_test.dart (66%)
rename catalyst_voices/packages/internal/{catalyst_voices_services => catalyst_voices_shared}/test/src/keychain/vault_keychain_provider_test.dart (79%)
rename catalyst_voices/packages/internal/{catalyst_voices_services => catalyst_voices_shared}/test/src/keychain/vault_keychain_test.dart (60%)
rename catalyst_voices/packages/internal/{catalyst_voices_services => catalyst_voices_shared}/test/src/storage/secure_storage_test.dart (96%)
rename catalyst_voices/packages/internal/{catalyst_voices_services => catalyst_voices_shared}/test/src/storage/storage_string_mixin_test.dart (95%)
rename catalyst_voices/packages/internal/{catalyst_voices_services => catalyst_voices_shared}/test/src/storage/vault/secure_storage_vault_test.dart (87%)
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_view_models/lib/src/authentication/access_control.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_view_models/lib/src/campaign/campaign_category_section.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_view_models/lib/src/campaign/campaign_info.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_view_models/lib/src/campaign/campaign_list_item.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_view_models/lib/src/campaign/campaign_stage.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_view_models/lib/src/menu/menu_item.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_view_models/lib/src/menu/popup_menu_item.dart
delete mode 100644 catalyst_voices/packages/internal/catalyst_voices_view_models/lib/src/proposal/guidance/guidance_type.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_view_models/lib/src/proposal/proposal_view_model.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_view_models/lib/src/session/session_status.dart
delete mode 100644 catalyst_voices/packages/internal/catalyst_voices_view_models/lib/src/treasury/campaign_setup.dart
delete mode 100644 catalyst_voices/packages/internal/catalyst_voices_view_models/lib/src/workspace/capability_and_feasibility.dart
delete mode 100644 catalyst_voices/packages/internal/catalyst_voices_view_models/lib/src/workspace/proposal_impact.dart
delete mode 100644 catalyst_voices/packages/internal/catalyst_voices_view_models/lib/src/workspace/proposal_setup.dart
delete mode 100644 catalyst_voices/packages/internal/catalyst_voices_view_models/lib/src/workspace/proposal_solution.dart
delete mode 100644 catalyst_voices/packages/internal/catalyst_voices_view_models/lib/src/workspace/proposal_summary.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_view_models/lib/src/workspace/workspace_proposal_list_item.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_view_models/lib/src/workspace/workspace_tab_type.dart
create mode 100644 catalyst_voices/packages/internal/catalyst_voices_view_models/test/campaign/campaign_stage_test.dart
create mode 100644 catalyst_voices/packages/libs/catalyst_cardano/catalyst_cardano/wallet-automation/utils/wallets/nufiUtils.ts
create mode 100644 catalyst_voices/packages/libs/catalyst_cardano/catalyst_cardano/wallet-automation/utils/wallets/yoroiUtils.ts
delete mode 100644 catalyst_voices/packages/libs/catalyst_cose/lib/src/catalyst_cose.dart
create mode 100644 catalyst_voices/packages/libs/catalyst_cose/lib/src/cose_constants.dart
create mode 100644 catalyst_voices/packages/libs/catalyst_cose/lib/src/cose_sign.dart
create mode 100644 catalyst_voices/packages/libs/catalyst_cose/lib/src/cose_sign1.dart
create mode 100644 catalyst_voices/packages/libs/catalyst_cose/lib/src/types/cose_headers.dart
create mode 100644 catalyst_voices/packages/libs/catalyst_cose/lib/src/types/string_or_int.dart
create mode 100644 catalyst_voices/packages/libs/catalyst_cose/lib/src/types/uuid.dart
create mode 100644 catalyst_voices/packages/libs/catalyst_cose/lib/src/utils/cbor_utils.dart
delete mode 100644 catalyst_voices/packages/libs/catalyst_cose/test/catalyst_cose_test.dart
create mode 100644 catalyst_voices/packages/libs/catalyst_cose/test/cose_sign1_test.dart
create mode 100644 catalyst_voices/packages/libs/catalyst_cose/test/cose_sign_test.dart
delete mode 100644 docs/src/architecture/08_concepts/signed_document_metadata/.pages
delete mode 100644 docs/src/architecture/08_concepts/signed_document_metadata/metadata.md
create mode 100644 docs/src/architecture/09_architecture_decisions/0009-uuid7-vs-ulid.md
diff --git a/.config/dictionaries/project.dic b/.config/dictionaries/project.dic
index f1b9a1c93f7..6fb00d63c76 100644
--- a/.config/dictionaries/project.dic
+++ b/.config/dictionaries/project.dic
@@ -22,6 +22,7 @@ auditability
Autolayout
autorecalculates
autoresizing
+autovalidate
backendpython
backgrounding
bech
@@ -59,6 +60,7 @@ collabs
commitlog
concatcp
coproposers
+COSE
coti
coverallsapp
CQLSH
@@ -77,6 +79,7 @@ delegators
devnet
DIND
dockerhub
+domcontentloaded
Dominik
dotenv
dotenvy
@@ -168,6 +171,7 @@ loguru
lovelace
lovelaces
LTRB
+Lynxx
mdlint
metadatum
metadatums
@@ -187,11 +191,13 @@ Multiplatform
myproject
Nami
nanos
+nathanbogale
NDEBUG
netifas
netkey
nextest
Nodetool
+NuFi
oapi
OCSP
Oleksandr
@@ -200,6 +206,7 @@ oneshot
openapi
opentelemetry
overprovisioned
+pageobject
Pbkdf2
pbxproj
Pdart
@@ -219,6 +226,7 @@ projectcatalyst
Prokhorenko
proptest
psql
+psycopg
Ptarget
pubkey
PUBLICKEY
@@ -283,7 +291,9 @@ testplan
testunit
thiserror
thollander
+Timelapse
timelike
+tkach
Toastify
todos
toggleable
@@ -292,6 +302,7 @@ tomjs
Traceback
traefik
trailings
+tstr
TXNZD
txos
Typer
@@ -299,6 +310,7 @@ unawaited
unchunk
Unlogged
unmanaged
+Unmarks
Unstaked
upskilling
UTXO
@@ -321,6 +333,7 @@ Wireframes
Wmissing
Wnullable
Woverlength
+Writedown
xcassets
xcconfig
xcfilelist
@@ -333,4 +346,4 @@ xprv
xpub
xpublic
xvfb
-yoroi
+yoroi
\ No newline at end of file
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 6be1963f41c..73619052f97 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -1,9 +1,13 @@
-/athena/ @stevenj @Mr-Leshiy @FelipeRosa @cong-or @saibatizoku
+/athena/ @stevenj @Mr-Leshiy @cong-or @saibatizoku @bkioshn @stanislav-tkach
-/catalyst_voices/ @minikin
+/catalyst_voices/ @dtscalac @damian-molinski @LynxLynxx
-/catalyst_voices/packages/libs/ @minikin @stevenj
+/catalyst_voices_packages/ @dtscalac @damian-molinski @LynxLynxx
-/catalyst-gateway/ @stevenj @Mr-Leshiy @FelipeRosa @cong-or @saibatizoku @minikin
+/catalyst-gateway/ @stevenj @Mr-Leshiy @cong-or @saibatizoku @bkioshn @stanislav-tkach
-.md @stevenj @minikin
+/catalyst-gateway-crates/ @stevenj @Mr-Leshiy @cong-or @saibatizoku @bkioshn @stanislav-tkach
+
+/docs/ @stevenj @neil-iohk @nathanbogale @minikin
+
+.md @stevenj @minikin
\ No newline at end of file
diff --git a/catalyst-gateway/Earthfile b/catalyst-gateway/Earthfile
index 1cde02848f7..bde5adb213f 100644
--- a/catalyst-gateway/Earthfile
+++ b/catalyst-gateway/Earthfile
@@ -124,3 +124,19 @@ check-builder-src-cache:
RUN diff ../src_fingerprint.txt ../src_fingerprint_uncached.txt \
|| (echo "ERROR: Source fingerprints do not match. Caching Error Detected!!" && exit 1) \
&& echo "Source fingerprints match. Caching OK."
+
+test:
+ FROM +builder-src
+
+ COPY docker-compose.yml .
+
+ ENV EVENT_DB_URL "postgres://catalyst-event-dev:CHANGE_ME@localhost/CatalystEventDev"
+
+ WITH DOCKER \
+ --compose "./docker-compose.yml" \
+ --load ./event-db+build \
+ --pull alpine:3.20.3 \
+ --service event-db-is-running
+ RUN --mount=$EARTHLY_RUST_CARGO_HOME_CACHE --mount=$EARTHLY_RUST_TARGET_CACHE \
+ cargo nextest run --release --run-ignored=only signed_docs
+ END
\ No newline at end of file
diff --git a/catalyst-gateway/bin/Cargo.toml b/catalyst-gateway/bin/Cargo.toml
index fbba8109c1b..75c578f6d92 100644
--- a/catalyst-gateway/bin/Cargo.toml
+++ b/catalyst-gateway/bin/Cargo.toml
@@ -15,7 +15,7 @@ repository.workspace = true
workspace = true
[dependencies]
-cardano-chain-follower = { version = "0.0.5", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "v0.0.9" }
+cardano-chain-follower = { version = "0.0.6", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "v0.0.10" }
c509-certificate = { version = "0.0.3", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "v0.0.3" }
rbac-registration = { version = "0.0.2", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "v0.0.8" }
@@ -43,6 +43,7 @@ tokio-postgres = { version = "0.7.12", features = [
"with-chrono-0_4",
"with-serde_json-1",
"with-time-0_3",
+ "with-uuid-1"
] }
tokio = { version = "1.41.0", features = ["rt", "macros", "rt-multi-thread"] }
dotenvy = "0.15.7"
@@ -77,7 +78,7 @@ poem-openapi = { version = "5.1.2", features = [
"url",
"chrono",
] }
-uuid = { version = "1.11.0", features = ["v4", "serde"] }
+uuid = { version = "1.11.0", features = ["v4", "v7", "serde"] }
ulid = { version = "1.1.3", features = ["serde", "uuid"] }
blake2b_simd = "1.0.2"
url = "2.5.3"
diff --git a/catalyst-gateway/bin/src/db/event/mod.rs b/catalyst-gateway/bin/src/db/event/mod.rs
index d0914f3a888..1bc4bd1d476 100644
--- a/catalyst-gateway/bin/src/db/event/mod.rs
+++ b/catalyst-gateway/bin/src/db/event/mod.rs
@@ -18,10 +18,11 @@ pub(crate) mod config;
pub(crate) mod error;
pub(crate) mod legacy;
pub(crate) mod schema_check;
+pub(crate) mod signed_docs;
/// Database version this crate matches.
/// Must equal the last Migrations Version Number from `event-db/migrations`.
-pub(crate) const DATABASE_SCHEMA_VERSION: i32 = 9;
+pub(crate) const DATABASE_SCHEMA_VERSION: i32 = 2;
/// Postgres Connection Manager DB Pool
type SqlDbPool = Arc>>;
@@ -212,7 +213,7 @@ impl EventDB {
///
/// The env var "`DATABASE_URL`" can be set directly as an anv var, or in a
/// `.env` file.
-pub(crate) fn establish_connection() {
+pub fn establish_connection() {
let (url, user, pass) = Settings::event_db_settings();
// This was pre-validated and can't fail, but provide default in the impossible case it
diff --git a/catalyst-gateway/bin/src/db/event/signed_docs/mod.rs b/catalyst-gateway/bin/src/db/event/signed_docs/mod.rs
new file mode 100644
index 00000000000..19ae3a854b3
--- /dev/null
+++ b/catalyst-gateway/bin/src/db/event/signed_docs/mod.rs
@@ -0,0 +1,32 @@
+//! Signed docs queries
+
+#[cfg(test)]
+mod tests;
+
+use super::EventDB;
+
+/// Insert sql query
+const INSERT_SIGNED_DOCS: &str = include_str!("./sql/insert_signed_documents.sql");
+
+/// Make an insert query into the `event-db` by adding data into the `signed_docs` table
+///
+/// * IF the record primary key (id,ver) does not exist, then add the new record. Return
+/// success.
+/// * IF the record does exist, but all values are the same as stored, return Success.
+/// * Otherwise return an error. (Can not over-write an existing record with new data).
+///
+/// # Arguments:
+/// - `id` is a UUID v7
+/// - `ver` is a UUID v7
+/// - `doc_type` is a UUID v4
+#[allow(dead_code)]
+pub(crate) async fn insert_signed_docs(
+ id: &uuid::Uuid, ver: &uuid::Uuid, doc_type: &uuid::Uuid, author: &String,
+ metadata: &Option, payload: &Option, raw: &Vec,
+) -> anyhow::Result<()> {
+ EventDB::modify(INSERT_SIGNED_DOCS, &[
+ id, ver, doc_type, author, metadata, payload, raw,
+ ])
+ .await?;
+ Ok(())
+}
diff --git a/catalyst-gateway/bin/src/db/event/signed_docs/sql/insert_signed_documents.sql b/catalyst-gateway/bin/src/db/event/signed_docs/sql/insert_signed_documents.sql
new file mode 100644
index 00000000000..61183ea693a
--- /dev/null
+++ b/catalyst-gateway/bin/src/db/event/signed_docs/sql/insert_signed_documents.sql
@@ -0,0 +1,12 @@
+INSERT INTO signed_docs
+(
+ id,
+ ver,
+ type,
+ author,
+ metadata,
+ payload,
+ raw
+)
+VALUES
+($1, $2, $3, $4, $5, $6, $7)
diff --git a/catalyst-gateway/bin/src/db/event/signed_docs/tests/mod.rs b/catalyst-gateway/bin/src/db/event/signed_docs/tests/mod.rs
new file mode 100644
index 00000000000..a65c9206adc
--- /dev/null
+++ b/catalyst-gateway/bin/src/db/event/signed_docs/tests/mod.rs
@@ -0,0 +1,50 @@
+//! Integration tests of the `signed docs` queries
+
+use super::*;
+use crate::db::event::establish_connection;
+
+#[ignore = "An integration test which requires a running EventDB instance, disabled from `testunit` CI run"]
+#[tokio::test]
+async fn some_test() {
+ establish_connection();
+
+ let docs = [
+ (
+ uuid::Uuid::now_v7(),
+ uuid::Uuid::now_v7(),
+ uuid::Uuid::new_v4(),
+ "Alex".to_string(),
+ &Some(serde_json::Value::Null),
+ &Some(serde_json::Value::Null),
+ vec![1, 2, 3, 4],
+ ),
+ (
+ uuid::Uuid::now_v7(),
+ uuid::Uuid::now_v7(),
+ uuid::Uuid::new_v4(),
+ "Steven".to_string(),
+ &Some(serde_json::Value::Null),
+ &Some(serde_json::Value::Null),
+ vec![5, 6, 7, 8],
+ ),
+ (
+ uuid::Uuid::now_v7(),
+ uuid::Uuid::now_v7(),
+ uuid::Uuid::new_v4(),
+ "Sasha".to_string(),
+ &None,
+ &None,
+ vec![9, 10, 11, 12],
+ ),
+ ];
+
+ for (id, ver, doc_type, author, metadata, payload, raw) in &docs {
+ insert_signed_docs(id, ver, doc_type, author, metadata, payload, raw)
+ .await
+ .unwrap();
+ // // try to insert the same data again
+ // insert_signed_docs(id, ver, doc_type, author, metadata, payload, raw)
+ // .await
+ // .unwrap();
+ }
+}
diff --git a/catalyst-gateway/bin/src/settings/mod.rs b/catalyst-gateway/bin/src/settings/mod.rs
index 28726514680..6be03945050 100644
--- a/catalyst-gateway/bin/src/settings/mod.rs
+++ b/catalyst-gateway/bin/src/settings/mod.rs
@@ -73,10 +73,6 @@ fn calculate_service_uuid() -> String {
#[derive(Args, Clone)]
#[clap(version = BUILD_INFO)]
pub(crate) struct ServiceSettings {
- /// Url to the postgres event db
- #[clap(long, env)]
- pub(crate) event_db_url: Option,
-
/// Logging level
#[clap(long, default_value = LOG_LEVEL_DEFAULT)]
pub(crate) log_level: LogLevel,
diff --git a/catalyst-gateway/blueprint.cue b/catalyst-gateway/blueprint.cue
index c81c19d56c6..9e36433f3f4 100644
--- a/catalyst-gateway/blueprint.cue
+++ b/catalyst-gateway/blueprint.cue
@@ -12,4 +12,9 @@ project: {
}
}
}
+ ci: {
+ targets: {
+ test: privileged: true
+ }
+ }
}
diff --git a/catalyst-gateway/docker-compose.yml b/catalyst-gateway/docker-compose.yml
index 4b2d833735b..00b2a348764 100644
--- a/catalyst-gateway/docker-compose.yml
+++ b/catalyst-gateway/docker-compose.yml
@@ -1,10 +1,7 @@
-version: "3"
-
services:
event-db:
image: event-db:latest
environment:
- # Required environment variables for migrations
- DB_HOST=localhost
- DB_PORT=5432
- DB_NAME=CatalystEventDev
@@ -16,7 +13,6 @@ services:
- INIT_AND_DROP_DB=true
- WITH_MIGRATIONS=true
- - WITH_SEED_DATA=true
ports:
- 5432:5432
healthcheck:
@@ -25,6 +21,14 @@ services:
timeout: 5s
retries: 10
+# it is a helper service to wait until the event-db will be ready
+# mainly its a trick for Earthly how to wait until service will be fully functional
+ event-db-is-running:
+ image: alpine:3.20.3
+ depends_on:
+ event-db:
+ condition: service_healthy
+
cat-gateway:
image: cat-gateway:latest
environment:
diff --git a/catalyst-gateway/event-db/Earthfile b/catalyst-gateway/event-db/Earthfile
index dac2e2647ca..4b004d1ea62 100644
--- a/catalyst-gateway/event-db/Earthfile
+++ b/catalyst-gateway/event-db/Earthfile
@@ -4,6 +4,7 @@
VERSION 0.8
IMPORT github.com/input-output-hk/catalyst-ci/earthly/postgresql:v3.2.24 AS postgresql-ci
+IMPORT github.com/input-output-hk/catalyst-ci/earthly/python:v3.2.24 AS python-ci
# cspell: words
@@ -41,24 +42,19 @@ local:
SAVE IMAGE --push --insecure $local_registry/event-db:latest
END
-
-# test the event db database schema
-# CI target : true
-#test:
-# FROM github.com/input-output-hk/catalyst-ci/earthly/postgresql:v2.9.2+postgres-base
-
-# COPY github.com/input-output-hk/catalyst-ci/earthly/utils:v2.9.2+shell-assert/assert.sh .
-
-# COPY ./docker-compose.yml .
-# WITH DOCKER \
-# --compose docker-compose.yml \
-# --load event-db:latest=(+build --with_historic_data=false) \
-# --service event-db \
-# --allow-privileged
-# RUN sleep 65;\
-# res=$(psql postgresql://catalyst-event-dev:CHANGE_ME@0.0.0.0:5432/CatalystEventDev -c "SELECT COUNT(*) FROM event");\
-
-# source assert.sh;\
-# expected=$(printf " count \n-------\n 5\n(1 row)");\
-# assert_eq "$expected" "$res"
-# END
+# Run the queries_tests.py
+test:
+ FROM python-ci+python-base
+
+ DO python-ci+BUILDER
+ COPY --dir tests .
+ COPY --dir queries .
+
+ WITH DOCKER \
+ --compose "./tests/docker-compose.yml" \
+ --load event-db:latest=+build \
+ --pull alpine:3.20.3 \
+ --service event-db-is-running \
+ --allow-privileged
+ RUN poetry run pytest -s -m ci
+ END
diff --git a/catalyst-gateway/event-db/blueprint.cue b/catalyst-gateway/event-db/blueprint.cue
index 1dad7a98b08..0d9ef5b2bff 100644
--- a/catalyst-gateway/event-db/blueprint.cue
+++ b/catalyst-gateway/event-db/blueprint.cue
@@ -1,2 +1,9 @@
version: "1.0.0"
-project: name: "gateway-event-db"
+project: {
+ name: "gateway-event-db"
+ ci: {
+ targets: {
+ test: privileged: true
+ }
+ }
+}
diff --git a/catalyst-gateway/event-db/migrations/V2__signed_documents.sql b/catalyst-gateway/event-db/migrations/V2__signed_documents.sql
index 523680ef9f2..28ff361d4a3 100644
--- a/catalyst-gateway/event-db/migrations/V2__signed_documents.sql
+++ b/catalyst-gateway/event-db/migrations/V2__signed_documents.sql
@@ -12,11 +12,11 @@
-- Signed Documents Storage Repository defintion.
CREATE TABLE IF NOT EXISTS signed_docs (
- id UUID NOT NULL, -- Actually a ULID
- ver UUID NOT NULL, -- Actually a ULID
- type UUID NOT NULL, -- Yes its a UUID this time
+ id UUID NOT NULL, -- UUID v7
+ ver UUID NOT NULL, -- UUID v7
+ type UUID NOT NULL, -- UUID v4
author TEXT NOT NULL,
- metadata JSONB NOT NULL,
+ metadata JSONB NULL,
payload JSONB NULL,
raw BYTEA NOT NULL,
diff --git a/catalyst-gateway/event-db/poetry.lock b/catalyst-gateway/event-db/poetry.lock
new file mode 100644
index 00000000000..9194944001f
--- /dev/null
+++ b/catalyst-gateway/event-db/poetry.lock
@@ -0,0 +1,311 @@
+# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand.
+
+[[package]]
+name = "colorama"
+version = "0.4.6"
+description = "Cross-platform colored terminal text."
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
+files = [
+ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
+ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
+]
+
+[[package]]
+name = "iniconfig"
+version = "2.0.0"
+description = "brain-dead simple config-ini parsing"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"},
+ {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
+]
+
+[[package]]
+name = "jinja2"
+version = "3.1.4"
+description = "A very fast and expressive template engine."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"},
+ {file = "jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"},
+]
+
+[package.dependencies]
+MarkupSafe = ">=2.0"
+
+[package.extras]
+i18n = ["Babel (>=2.7)"]
+
+[[package]]
+name = "loguru"
+version = "0.7.3"
+description = "Python logging made (stupidly) simple"
+optional = false
+python-versions = "<4.0,>=3.5"
+files = [
+ {file = "loguru-0.7.3-py3-none-any.whl", hash = "sha256:31a33c10c8e1e10422bfd431aeb5d351c7cf7fa671e3c4df004162264b28220c"},
+ {file = "loguru-0.7.3.tar.gz", hash = "sha256:19480589e77d47b8d85b2c827ad95d49bf31b0dcde16593892eb51dd18706eb6"},
+]
+
+[package.dependencies]
+colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""}
+win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""}
+
+[package.extras]
+dev = ["Sphinx (==8.1.3)", "build (==1.2.2)", "colorama (==0.4.5)", "colorama (==0.4.6)", "exceptiongroup (==1.1.3)", "freezegun (==1.1.0)", "freezegun (==1.5.0)", "mypy (==v0.910)", "mypy (==v0.971)", "mypy (==v1.13.0)", "mypy (==v1.4.1)", "myst-parser (==4.0.0)", "pre-commit (==4.0.1)", "pytest (==6.1.2)", "pytest (==8.3.2)", "pytest-cov (==2.12.1)", "pytest-cov (==5.0.0)", "pytest-cov (==6.0.0)", "pytest-mypy-plugins (==1.9.3)", "pytest-mypy-plugins (==3.1.0)", "sphinx-rtd-theme (==3.0.2)", "tox (==3.27.1)", "tox (==4.23.2)", "twine (==6.0.1)"]
+
+[[package]]
+name = "markupsafe"
+version = "3.0.2"
+description = "Safely add untrusted strings to HTML/XML markup."
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"},
+ {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"},
+ {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579"},
+ {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d"},
+ {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb"},
+ {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b"},
+ {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c"},
+ {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171"},
+ {file = "MarkupSafe-3.0.2-cp310-cp310-win32.whl", hash = "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50"},
+ {file = "MarkupSafe-3.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a"},
+ {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d"},
+ {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93"},
+ {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832"},
+ {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84"},
+ {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca"},
+ {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798"},
+ {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e"},
+ {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4"},
+ {file = "MarkupSafe-3.0.2-cp311-cp311-win32.whl", hash = "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d"},
+ {file = "MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b"},
+ {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf"},
+ {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225"},
+ {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028"},
+ {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8"},
+ {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c"},
+ {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557"},
+ {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22"},
+ {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48"},
+ {file = "MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30"},
+ {file = "MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f"},
+ {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a"},
+ {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff"},
+ {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13"},
+ {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144"},
+ {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29"},
+ {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0"},
+ {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0"},
+ {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178"},
+ {file = "MarkupSafe-3.0.2-cp39-cp39-win32.whl", hash = "sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f"},
+ {file = "MarkupSafe-3.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a"},
+ {file = "markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0"},
+]
+
+[[package]]
+name = "packaging"
+version = "24.2"
+description = "Core utilities for Python packages"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"},
+ {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"},
+]
+
+[[package]]
+name = "pluggy"
+version = "1.5.0"
+description = "plugin and hook calling mechanisms for python"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"},
+ {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"},
+]
+
+[package.extras]
+dev = ["pre-commit", "tox"]
+testing = ["pytest", "pytest-benchmark"]
+
+[[package]]
+name = "psycopg"
+version = "3.2.3"
+description = "PostgreSQL database adapter for Python"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "psycopg-3.2.3-py3-none-any.whl", hash = "sha256:644d3973fe26908c73d4be746074f6e5224b03c1101d302d9a53bf565ad64907"},
+ {file = "psycopg-3.2.3.tar.gz", hash = "sha256:a5764f67c27bec8bfac85764d23c534af2c27b893550377e37ce59c12aac47a2"},
+]
+
+[package.dependencies]
+typing-extensions = {version = ">=4.6", markers = "python_version < \"3.13\""}
+tzdata = {version = "*", markers = "sys_platform == \"win32\""}
+
+[package.extras]
+binary = ["psycopg-binary (==3.2.3)"]
+c = ["psycopg-c (==3.2.3)"]
+dev = ["ast-comments (>=1.1.2)", "black (>=24.1.0)", "codespell (>=2.2)", "dnspython (>=2.1)", "flake8 (>=4.0)", "mypy (>=1.11)", "types-setuptools (>=57.4)", "wheel (>=0.37)"]
+docs = ["Sphinx (>=5.0)", "furo (==2022.6.21)", "sphinx-autobuild (>=2021.3.14)", "sphinx-autodoc-typehints (>=1.12)"]
+pool = ["psycopg-pool"]
+test = ["anyio (>=4.0)", "mypy (>=1.11)", "pproxy (>=2.7)", "pytest (>=6.2.5)", "pytest-cov (>=3.0)", "pytest-randomly (>=3.5)"]
+
+[[package]]
+name = "psycopg-binary"
+version = "3.2.3"
+description = "PostgreSQL database adapter for Python -- C optimisation distribution"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "psycopg_binary-3.2.3-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:965455eac8547f32b3181d5ec9ad8b9be500c10fe06193543efaaebe3e4ce70c"},
+ {file = "psycopg_binary-3.2.3-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:71adcc8bc80a65b776510bc39992edf942ace35b153ed7a9c6c573a6849ce308"},
+ {file = "psycopg_binary-3.2.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f73adc05452fb85e7a12ed3f69c81540a8875960739082e6ea5e28c373a30774"},
+ {file = "psycopg_binary-3.2.3-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e8630943143c6d6ca9aefc88bbe5e76c90553f4e1a3b2dc339e67dc34aa86f7e"},
+ {file = "psycopg_binary-3.2.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3bffb61e198a91f712cc3d7f2d176a697cb05b284b2ad150fb8edb308eba9002"},
+ {file = "psycopg_binary-3.2.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc4fa2240c9fceddaa815a58f29212826fafe43ce80ff666d38c4a03fb036955"},
+ {file = "psycopg_binary-3.2.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:192a5f8496e6e1243fdd9ac20e117e667c0712f148c5f9343483b84435854c78"},
+ {file = "psycopg_binary-3.2.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:64dc6e9ec64f592f19dc01a784e87267a64a743d34f68488924251253da3c818"},
+ {file = "psycopg_binary-3.2.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:79498df398970abcee3d326edd1d4655de7d77aa9aecd578154f8af35ce7bbd2"},
+ {file = "psycopg_binary-3.2.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:949551752930d5e478817e0b49956350d866b26578ced0042a61967e3fcccdea"},
+ {file = "psycopg_binary-3.2.3-cp310-cp310-win_amd64.whl", hash = "sha256:80a2337e2dfb26950894c8301358961430a0304f7bfe729d34cc036474e9c9b1"},
+ {file = "psycopg_binary-3.2.3-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:6d8f2144e0d5808c2e2aed40fbebe13869cd00c2ae745aca4b3b16a435edb056"},
+ {file = "psycopg_binary-3.2.3-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:94253be2b57ef2fea7ffe08996067aabf56a1eb9648342c9e3bad9e10c46e045"},
+ {file = "psycopg_binary-3.2.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fda0162b0dbfa5eaed6cdc708179fa27e148cb8490c7d62e5cf30713909658ea"},
+ {file = "psycopg_binary-3.2.3-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2c0419cdad8c70eaeb3116bb28e7b42d546f91baf5179d7556f230d40942dc78"},
+ {file = "psycopg_binary-3.2.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:74fbf5dd3ef09beafd3557631e282f00f8af4e7a78fbfce8ab06d9cd5a789aae"},
+ {file = "psycopg_binary-3.2.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d784f614e4d53050cbe8abf2ae9d1aaacf8ed31ce57b42ce3bf2a48a66c3a5c"},
+ {file = "psycopg_binary-3.2.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4e76ce2475ed4885fe13b8254058be710ec0de74ebd8ef8224cf44a9a3358e5f"},
+ {file = "psycopg_binary-3.2.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5938b257b04c851c2d1e6cb2f8c18318f06017f35be9a5fe761ee1e2e344dfb7"},
+ {file = "psycopg_binary-3.2.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:257c4aea6f70a9aef39b2a77d0658a41bf05c243e2bf41895eb02220ac6306f3"},
+ {file = "psycopg_binary-3.2.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:06b5cc915e57621eebf2393f4173793ed7e3387295f07fed93ed3fb6a6ccf585"},
+ {file = "psycopg_binary-3.2.3-cp311-cp311-win_amd64.whl", hash = "sha256:09baa041856b35598d335b1a74e19a49da8500acedf78164600694c0ba8ce21b"},
+ {file = "psycopg_binary-3.2.3-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:48f8ca6ee8939bab760225b2ab82934d54330eec10afe4394a92d3f2a0c37dd6"},
+ {file = "psycopg_binary-3.2.3-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:5361ea13c241d4f0ec3f95e0bf976c15e2e451e9cc7ef2e5ccfc9d170b197a40"},
+ {file = "psycopg_binary-3.2.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb987f14af7da7c24f803111dbc7392f5070fd350146af3345103f76ea82e339"},
+ {file = "psycopg_binary-3.2.3-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0463a11b1cace5a6aeffaf167920707b912b8986a9c7920341c75e3686277920"},
+ {file = "psycopg_binary-3.2.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8b7be9a6c06518967b641fb15032b1ed682fd3b0443f64078899c61034a0bca6"},
+ {file = "psycopg_binary-3.2.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64a607e630d9f4b2797f641884e52b9f8e239d35943f51bef817a384ec1678fe"},
+ {file = "psycopg_binary-3.2.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:fa33ead69ed133210d96af0c63448b1385df48b9c0247eda735c5896b9e6dbbf"},
+ {file = "psycopg_binary-3.2.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:1f8b0d0e99d8e19923e6e07379fa00570be5182c201a8c0b5aaa9a4d4a4ea20b"},
+ {file = "psycopg_binary-3.2.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:709447bd7203b0b2debab1acec23123eb80b386f6c29e7604a5d4326a11e5bd6"},
+ {file = "psycopg_binary-3.2.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5e37d5027e297a627da3551a1e962316d0f88ee4ada74c768f6c9234e26346d9"},
+ {file = "psycopg_binary-3.2.3-cp312-cp312-win_amd64.whl", hash = "sha256:261f0031ee6074765096a19b27ed0f75498a8338c3dcd7f4f0d831e38adf12d1"},
+ {file = "psycopg_binary-3.2.3-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:41fdec0182efac66b27478ac15ef54c9ebcecf0e26ed467eb7d6f262a913318b"},
+ {file = "psycopg_binary-3.2.3-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:07d019a786eb020c0f984691aa1b994cb79430061065a694cf6f94056c603d26"},
+ {file = "psycopg_binary-3.2.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4c57615791a337378fe5381143259a6c432cdcbb1d3e6428bfb7ce59fff3fb5c"},
+ {file = "psycopg_binary-3.2.3-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e8eb9a4e394926b93ad919cad1b0a918e9b4c846609e8c1cfb6b743683f64da0"},
+ {file = "psycopg_binary-3.2.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5905729668ef1418bd36fbe876322dcb0f90b46811bba96d505af89e6fbdce2f"},
+ {file = "psycopg_binary-3.2.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd65774ed7d65101b314808b6893e1a75b7664f680c3ef18d2e5c84d570fa393"},
+ {file = "psycopg_binary-3.2.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:700679c02f9348a0d0a2adcd33a0275717cd0d0aee9d4482b47d935023629505"},
+ {file = "psycopg_binary-3.2.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:96334bb64d054e36fed346c50c4190bad9d7c586376204f50bede21a913bf942"},
+ {file = "psycopg_binary-3.2.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:9099e443d4cc24ac6872e6a05f93205ba1a231b1a8917317b07c9ef2b955f1f4"},
+ {file = "psycopg_binary-3.2.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1985ab05e9abebfbdf3163a16ebb37fbc5d49aff2bf5b3d7375ff0920bbb54cd"},
+ {file = "psycopg_binary-3.2.3-cp313-cp313-win_amd64.whl", hash = "sha256:e90352d7b610b4693fad0feea48549d4315d10f1eba5605421c92bb834e90170"},
+ {file = "psycopg_binary-3.2.3-cp38-cp38-macosx_12_0_x86_64.whl", hash = "sha256:69320f05de8cdf4077ecd7fefdec223890eea232af0d58f2530cbda2871244a0"},
+ {file = "psycopg_binary-3.2.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4926ea5c46da30bec4a85907aa3f7e4ea6313145b2aa9469fdb861798daf1502"},
+ {file = "psycopg_binary-3.2.3-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c64c4cd0d50d5b2288ab1bcb26c7126c772bbdebdfadcd77225a77df01c4a57e"},
+ {file = "psycopg_binary-3.2.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05a1bdce30356e70a05428928717765f4a9229999421013f41338d9680d03a63"},
+ {file = "psycopg_binary-3.2.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ad357e426b0ea5c3043b8ec905546fa44b734bf11d33b3da3959f6e4447d350"},
+ {file = "psycopg_binary-3.2.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:967b47a0fd237aa17c2748fdb7425015c394a6fb57cdad1562e46a6eb070f96d"},
+ {file = "psycopg_binary-3.2.3-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:71db8896b942770ed7ab4efa59b22eee5203be2dfdee3c5258d60e57605d688c"},
+ {file = "psycopg_binary-3.2.3-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:2773f850a778575dd7158a6dd072f7925b67f3ba305e2003538e8831fec77a1d"},
+ {file = "psycopg_binary-3.2.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:aeddf7b3b3f6e24ccf7d0edfe2d94094ea76b40e831c16eff5230e040ce3b76b"},
+ {file = "psycopg_binary-3.2.3-cp38-cp38-win_amd64.whl", hash = "sha256:824c867a38521d61d62b60aca7db7ca013a2b479e428a0db47d25d8ca5067410"},
+ {file = "psycopg_binary-3.2.3-cp39-cp39-macosx_12_0_x86_64.whl", hash = "sha256:9994f7db390c17fc2bd4c09dca722fd792ff8a49bb3bdace0c50a83f22f1767d"},
+ {file = "psycopg_binary-3.2.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1303bf8347d6be7ad26d1362af2c38b3a90b8293e8d56244296488ee8591058e"},
+ {file = "psycopg_binary-3.2.3-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:842da42a63ecb32612bb7f5b9e9f8617eab9bc23bd58679a441f4150fcc51c96"},
+ {file = "psycopg_binary-3.2.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2bb342a01c76f38a12432848e6013c57eb630103e7556cf79b705b53814c3949"},
+ {file = "psycopg_binary-3.2.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd40af959173ea0d087b6b232b855cfeaa6738f47cb2a0fd10a7f4fa8b74293f"},
+ {file = "psycopg_binary-3.2.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:9b60b465773a52c7d4705b0a751f7f1cdccf81dd12aee3b921b31a6e76b07b0e"},
+ {file = "psycopg_binary-3.2.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:fc6d87a1c44df8d493ef44988a3ded751e284e02cdf785f746c2d357e99782a6"},
+ {file = "psycopg_binary-3.2.3-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:f0b018e37608c3bfc6039a1dc4eb461e89334465a19916be0153c757a78ea426"},
+ {file = "psycopg_binary-3.2.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:2a29f5294b0b6360bfda69653697eff70aaf2908f58d1073b0acd6f6ab5b5a4f"},
+ {file = "psycopg_binary-3.2.3-cp39-cp39-win_amd64.whl", hash = "sha256:e56b1fd529e5dde2d1452a7d72907b37ed1b4f07fdced5d8fb1e963acfff6749"},
+]
+
+[[package]]
+name = "pytest"
+version = "8.3.4"
+description = "pytest: simple powerful testing with Python"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "pytest-8.3.4-py3-none-any.whl", hash = "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6"},
+ {file = "pytest-8.3.4.tar.gz", hash = "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761"},
+]
+
+[package.dependencies]
+colorama = {version = "*", markers = "sys_platform == \"win32\""}
+iniconfig = "*"
+packaging = "*"
+pluggy = ">=1.5,<2"
+
+[package.extras]
+dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
+
+[[package]]
+name = "typing-extensions"
+version = "4.12.2"
+description = "Backported and Experimental Type Hints for Python 3.8+"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"},
+ {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"},
+]
+
+[[package]]
+name = "tzdata"
+version = "2024.2"
+description = "Provider of IANA time zone data"
+optional = false
+python-versions = ">=2"
+files = [
+ {file = "tzdata-2024.2-py2.py3-none-any.whl", hash = "sha256:a48093786cdcde33cad18c2555e8532f34422074448fbc874186f0abd79565cd"},
+ {file = "tzdata-2024.2.tar.gz", hash = "sha256:7d85cc416e9382e69095b7bdf4afd9e3880418a2413feec7069d533d6b4e31cc"},
+]
+
+[[package]]
+name = "win32-setctime"
+version = "1.2.0"
+description = "A small Python utility to set file creation time on Windows"
+optional = false
+python-versions = ">=3.5"
+files = [
+ {file = "win32_setctime-1.2.0-py3-none-any.whl", hash = "sha256:95d644c4e708aba81dc3704a116d8cbc974d70b3bdb8be1d150e36be6e9d1390"},
+ {file = "win32_setctime-1.2.0.tar.gz", hash = "sha256:ae1fdf948f5640aae05c511ade119313fb6a30d7eabe25fef9764dca5873c4c0"},
+]
+
+[package.extras]
+dev = ["black (>=19.3b0)", "pytest (>=4.6.2)"]
+
+[metadata]
+lock-version = "2.0"
+python-versions = "^3.11"
+content-hash = "f1cfae8e203124329bc62902795c307371fa78930a3aabc9c8cd41a889b5298e"
diff --git a/catalyst-gateway/event-db/pyproject.toml b/catalyst-gateway/event-db/pyproject.toml
new file mode 100644
index 00000000000..d7447218181
--- /dev/null
+++ b/catalyst-gateway/event-db/pyproject.toml
@@ -0,0 +1,23 @@
+# cspell: words bitcoinlib
+
+[tool.poetry]
+name = "tests"
+version = "0.1.0"
+description = ""
+authors = []
+readme = "Readme.md"
+license = "MIT or Apache-2.0"
+
+[tool.poetry.dependencies]
+python = "^3.11"
+loguru = "^0.7.2"
+pytest = "^8.0.0"
+psycopg = "3.2.3"
+psycopg-binary = "^3.2.3"
+jinja2 = "^3.1.4"
+
+[tool.pytest.ini_options]
+markers = [
+ "ci: marks tests to be run in ci",
+ "nightly: marks tests to be run nightly",
+]
\ No newline at end of file
diff --git a/catalyst-gateway/event-db/queries/insert_signed_documents.sql b/catalyst-gateway/event-db/queries/insert_signed_documents.sql
new file mode 100644
index 00000000000..b5d79222259
--- /dev/null
+++ b/catalyst-gateway/event-db/queries/insert_signed_documents.sql
@@ -0,0 +1,22 @@
+INSERT INTO signed_docs
+(
+ id,
+ ver,
+ type,
+ author,
+ metadata,
+ payload,
+ raw
+)
+VALUES
+($1, $2, $3, $4, $5, $6, $7)
+ON CONFLICT (id, ver) DO UPDATE
+SET
+type = signed_docs.type
+
+WHERE
+signed_docs.type = excluded.type
+AND signed_docs.author = excluded.author
+AND signed_docs.metadata = excluded.metadata
+AND signed_docs.payload = excluded.payload
+AND signed_docs.raw = excluded.raw
diff --git a/catalyst-gateway/event-db/queries/select_signed_documents.sql.jinja b/catalyst-gateway/event-db/queries/select_signed_documents.sql.jinja
new file mode 100644
index 00000000000..fb4effa7fb3
--- /dev/null
+++ b/catalyst-gateway/event-db/queries/select_signed_documents.sql.jinja
@@ -0,0 +1,12 @@
+SELECT
+ signed_docs.type,
+ signed_docs.author,
+ signed_docs.metadata,
+ signed_docs.payload,
+ signed_docs.raw
+FROM signed_docs
+WHERE
+ signed_docs.id = '{{ id }}'
+ {% if ver %} AND signed_docs.ver = '{{ ver }}' {% endif %}
+ORDER BY signed_docs.ver DESC
+LIMIT 1
diff --git a/catalyst-gateway/event-db/queries/select_signed_documents_2.sql.jinja b/catalyst-gateway/event-db/queries/select_signed_documents_2.sql.jinja
new file mode 100644
index 00000000000..fda56391dbf
--- /dev/null
+++ b/catalyst-gateway/event-db/queries/select_signed_documents_2.sql.jinja
@@ -0,0 +1,12 @@
+SELECT
+ signed_docs.id,
+ signed_docs.ver,
+ signed_docs.type,
+ signed_docs.author,
+ signed_docs.metadata
+FROM signed_docs
+WHERE
+ {{ conditions }}
+ORDER BY signed_docs.type DESC, signed_docs.id DESC, signed_docs.ver DESC
+{% if limit %} LIMIT {{ limit }} {% endif %}
+{% if offset %} OFFSET {{ offset }} {% endif %}
diff --git a/catalyst-gateway/event-db/tests/docker-compose.yml b/catalyst-gateway/event-db/tests/docker-compose.yml
new file mode 100644
index 00000000000..4c9801de859
--- /dev/null
+++ b/catalyst-gateway/event-db/tests/docker-compose.yml
@@ -0,0 +1,30 @@
+services:
+ event-db:
+ image: event-db:latest
+ environment:
+ - DB_HOST=localhost
+ - DB_PORT=5432
+ - DB_NAME=CatalystEventDev
+ - DB_DESCRIPTION="Catalyst Event DB"
+ - DB_SUPERUSER=postgres
+ - DB_SUPERUSER_PASSWORD=postgres
+ - DB_USER=catalyst-event-dev
+ - DB_USER_PASSWORD=CHANGE_ME
+
+ - INIT_AND_DROP_DB=true
+ - WITH_MIGRATIONS=true
+ ports:
+ - 5432:5432
+ healthcheck:
+ test: ["CMD-SHELL", "pg_isready -U $${DB_SUPERUSER} -d $${DB_SUPERUSER_PASSWORD}"]
+ interval: 10s
+ timeout: 5s
+ retries: 10
+
+# it is a helper service to wait until the event-db will be ready
+# mainly its a trick for Earthly how to wait until service will be fully functional
+ event-db-is-running:
+ image: alpine:3.20.3
+ depends_on:
+ event-db:
+ condition: service_healthy
diff --git a/catalyst-gateway/event-db/tests/test_signed_docs_queries.py b/catalyst-gateway/event-db/tests/test_signed_docs_queries.py
new file mode 100644
index 00000000000..3eaad1af525
--- /dev/null
+++ b/catalyst-gateway/event-db/tests/test_signed_docs_queries.py
@@ -0,0 +1,147 @@
+import psycopg
+import pytest
+import jinja2
+
+
+jinja_env = jinja2.Environment(
+ loader=jinja2.FileSystemLoader("./queries/"),
+)
+EVENT_DB_URL = "postgres://catalyst-event-dev:CHANGE_ME@localhost/CatalystEventDev"
+
+
+class SignedData:
+ def __init__(
+ self,
+ id: str,
+ ver: str,
+ doc_type: str,
+ author: str,
+ metadata: str,
+ payload: str,
+ raw: bytes,
+ ):
+ self.id = id
+ self.ver = ver
+ self.doc_type = doc_type
+ self.author = author
+ self.metadata = metadata
+ self.payload = payload
+ self.raw = raw
+
+
+@pytest.mark.ci
+def test_signed_docs_queries():
+ with psycopg.connect(EVENT_DB_URL) as conn:
+ docs = [
+ SignedData(
+ id="3764e30b-9bb5-4a34-906e-f4de1845e8bf",
+ ver="299255cb-9f53-46ec-8e24-4360b9d374bd",
+ doc_type="c17f59b2-1304-4a75-923e-00795add70af",
+ author="Alex",
+ metadata="{}",
+ payload="{}",
+ raw=b"bytes1",
+ ),
+ SignedData(
+ id="4ee05138-e85b-48b4-91c2-2a45a74a0a82",
+ ver="3cd78d6c-9388-47ab-9a65-f3a84c76190f",
+ doc_type="fec1b996-ad89-4fab-a787-6568f42b00b1",
+ author="Steven",
+ metadata="{}",
+ payload="{}",
+ raw=b"bytes2",
+ ),
+ ]
+
+ insert_signed_documents_query(conn, docs)
+ # try insert the same values
+ insert_signed_documents_query(conn, docs)
+ select_signed_documents_query(conn, docs)
+ select_signed_documents_2_query(conn, docs)
+
+ # try insert the same id and ver, but with the different other data
+ docs[0].author = "Sasha"
+ docs[1].author = "Sasha"
+ should_panic(
+ lambda: insert_signed_documents_query(conn, docs),
+ "insert_signed_documents_query should fail",
+ )
+ should_panic(
+ lambda: select_signed_documents_query(conn, docs),
+ "select_signed_documents_query should fail",
+ )
+ should_panic(
+ lambda: select_signed_documents_2_query(conn, docs),
+ "select_signed_documents_2_query should fail",
+ )
+
+
+def insert_signed_documents_query(conn, docs: [SignedData]):
+ sql_stmt = open("./queries/insert_signed_documents.sql", "r").read()
+ sql_stmt = (
+ sql_stmt.replace("$1", "%s")
+ .replace("$2", "%s")
+ .replace("$3", "%s")
+ .replace("$4", "%s")
+ .replace("$5", "%s")
+ .replace("$6", "%s")
+ .replace("$7", "%s")
+ )
+ for doc in docs:
+ conn.execute(
+ sql_stmt,
+ (
+ doc.id,
+ doc.ver,
+ doc.doc_type,
+ doc.author,
+ doc.metadata,
+ doc.payload,
+ doc.raw,
+ ),
+ )
+
+
+def select_signed_documents_query(conn, docs: [SignedData]):
+ template = jinja_env.get_template("select_signed_documents.sql.jinja")
+ for doc in docs:
+ sql_stmt = template.render(
+ {
+ "id": doc.id,
+ "ver": doc.ver,
+ }
+ )
+ cur = conn.execute(sql_stmt)
+ (doc_type, author, metadata, payload, raw) = cur.fetchone()
+ assert str(doc_type) == doc.doc_type
+ assert author == doc.author
+ assert str(metadata) == doc.metadata
+ assert str(payload) == doc.payload
+ assert raw == doc.raw
+
+
+def select_signed_documents_2_query(conn, docs: [SignedData]):
+ template = jinja_env.get_template("select_signed_documents_2.sql.jinja")
+ for doc in docs:
+ sql_stmt = template.render(
+ {
+ "conditions": f"signed_docs.id = '{doc.id}' AND signed_docs.ver = '{doc.ver}'",
+ "limit": 1,
+ "offset": 0,
+ }
+ )
+ cur = conn.execute(sql_stmt)
+ (id, ver, doc_type, author, metadata) = cur.fetchone()
+ assert str(id) == doc.id
+ assert str(ver) == doc.ver
+ assert str(doc_type) == doc.doc_type
+ assert author == doc.author
+ assert str(metadata) == doc.metadata
+
+
+def should_panic(func, msg: str):
+ try:
+ func()
+ assert False, msg
+ except:
+ pass
diff --git a/catalyst_voices/.gitignore b/catalyst_voices/.gitignore
index 870c49c28a0..361c63c808d 100644
--- a/catalyst_voices/.gitignore
+++ b/catalyst_voices/.gitignore
@@ -1,5 +1,6 @@
### Dart ###
# See https://www.dartlang.org/guides/libraries/private-files
+devtools_options.yaml
# Generated files from code generation tools
diff --git a/catalyst_voices/Earthfile b/catalyst_voices/Earthfile
index 8cbe449c2ee..15cd041e617 100644
--- a/catalyst_voices/Earthfile
+++ b/catalyst_voices/Earthfile
@@ -19,13 +19,13 @@ builder:
DO flutter-ci+BOOTSTRAP
# Creates filtered OpenAPI spec
-# Takes json file from openapi-filter from /packages/internal/catalyst_voices_services
+# Takes json file from openapi-filter from /packages/internal/catalyst_voices_repositories
filter-openapi:
FROM node:18
- WORKDIR /packages/internal/catalyst_voices_services
+ WORKDIR /packages/internal/catalyst_voices_repositories
COPY catalyst-gateway+build/doc/cat-gateway-api.json openapi/cat-gateway-api.json
- COPY packages/internal/catalyst_voices_services/openapi-filters.json openapi-filters.json
+ COPY packages/internal/catalyst_voices_repositories/openapi-filters.json openapi-filters.json
RUN npm install -g openapi-format
RUN openapi-format openapi/cat-gateway-api.json -o openapi/filtered-openapi.json --filterFile openapi-filters.json --verbose
@@ -40,19 +40,19 @@ filter-openapi:
# It accepts [save_locally] ARG that when true place the artifacts in the
# proper folders
# It accepts [filter_openapi] ARG that when true filter the openapi spec
-# using filters from /packages/internal/catalyst_voices_services/openapi-filters.json
+# using filters from /packages/internal/catalyst_voices_repositories/openapi-filters.json
code-generator:
ARG save_locally=false
ARG filter_openapi=true
FROM +builder
- LET gen_code_path = lib/generated/catalyst_gateway
- LET local_gen_code_path = packages/internal/catalyst_voices_services/lib/generated/catalyst_gateway/
+ LET gen_code_path = lib/generated/api
+ LET local_gen_code_path = packages/internal/catalyst_voices_repositories/lib/generated/api/
RUN melos l10n
RUN melos build_runner
IF [ $save_locally = true ]
- RUN find . \( -name "*.g.dart" -o -name "*.freezed.dart" -o -name "*.chopper.dart" -o -name "*.swagger.dart" -o -name "*.openapi.dart" -o -name "*.gen.dart" -o -name "catalyst_voices_localizations*.dart" -o -name "cat_gateway_api.*.swagger.*" \)
+ RUN find . \( -name "*.g.dart" -o -name "*.freezed.dart" -o -name "*.chopper.dart" -o -name "*.swagger.dart" -o -name "*.openapi.dart" -o -name "*.gen.dart" -o -name "catalyst_voices_localizations*.dart" -o -name "cat_gateway.*.swagger.*" \)
FOR generated_file IN $(find . \( -name "*.g.dart" -o -name "*.freezed.dart" -o -name "*.chopper.dart" -o -name "*.swagger.dart" -o -name "*.openapi.dart" -o -name "*.gen.dart" -o -name "catalyst_voices_localizations*.dart" -o -name "cat_gateway_api.*.swagger.*" \))
SAVE ARTIFACT $generated_file AS LOCAL $generated_file
@@ -60,12 +60,12 @@ code-generator:
ELSE
SAVE ARTIFACT .
END
- WORKDIR packages/internal/catalyst_voices_services
+ WORKDIR packages/internal/catalyst_voices_repositories
IF [ $filter_openapi = true ]
- COPY +filter-openapi/filtered-openapi.json openapi/cat-gateway-api.json
+ COPY +filter-openapi/filtered-openapi.json openapi/cat-gateway.json
ELSE
- COPY catalyst-gateway+build/doc/cat-gateway-api.json openapi/cat-gateway-api.json
+ COPY catalyst-gateway+build/doc/cat-gateway-api.json openapi/cat-gateway.json
END
DO flutter-ci+OPENAPI_CODE_GEN \
diff --git a/catalyst_voices/apps/voices/integration_test/Earthfile b/catalyst_voices/apps/voices/integration_test/Earthfile
index 75f0f3de6c8..84470172b61 100644
--- a/catalyst_voices/apps/voices/integration_test/Earthfile
+++ b/catalyst_voices/apps/voices/integration_test/Earthfile
@@ -21,7 +21,7 @@ integration-test-web:
# IF [ $browser = "edge" && $TARGETARCH = "amd64" ]]
# LET driver = "msedgedriver"
# END
-
+
WORKDIR /frontend/apps/voices
RUN ($driver --port=$driver_port > $driver.log &) && \
diff --git a/catalyst_voices/apps/voices/integration_test/all_test.dart b/catalyst_voices/apps/voices/integration_test/all_test.dart
new file mode 100644
index 00000000000..550f5872a25
--- /dev/null
+++ b/catalyst_voices/apps/voices/integration_test/all_test.dart
@@ -0,0 +1,17 @@
+import 'package:catalyst_voices/configs/bootstrap.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'package:integration_test/integration_test.dart';
+
+import 'app_test.dart' as app_test;
+import 'onboarding_test.dart' as onboarding_test;
+
+void main() async {
+ IntegrationTestWidgetsFlutterBinding.ensureInitialized();
+
+ setUpAll(() async {
+ await bootstrap(router: buildAppRouter());
+ });
+
+ app_test.main();
+ onboarding_test.main();
+}
diff --git a/catalyst_voices/apps/voices/integration_test/app_test.dart b/catalyst_voices/apps/voices/integration_test/app_test.dart
index 9c9bad35d45..e2d34b294dd 100644
--- a/catalyst_voices/apps/voices/integration_test/app_test.dart
+++ b/catalyst_voices/apps/voices/integration_test/app_test.dart
@@ -1,20 +1,127 @@
import 'package:catalyst_voices/app/view/app.dart';
import 'package:catalyst_voices/configs/bootstrap.dart';
+import 'package:catalyst_voices/routes/routes.dart';
+import 'package:catalyst_voices_models/catalyst_voices_models.dart';
import 'package:flutter_test/flutter_test.dart';
-import 'package:integration_test/integration_test.dart';
-
-void main() {
- IntegrationTestWidgetsFlutterBinding.ensureInitialized();
-
- group('End to end tests', () {
- testWidgets('run app', (tester) async {
- final args = await bootstrap();
- await tester.pumpWidget(App(routerConfig: args.routerConfig));
- // let the application load
- await tester.pump(const Duration(seconds: 5));
- // pump and settle every 100ms to simulate almost production-like FPS
- await tester.pumpAndSettle(const Duration(milliseconds: 100));
- expect(find.text('Coming'), findsOneWidget);
- });
+import 'package:go_router/go_router.dart';
+import 'package:patrol_finders/patrol_finders.dart';
+
+import 'pageobject/app_bar_page.dart';
+import 'pageobject/overall_spaces_page.dart';
+import 'pageobject/spaces_drawer_page.dart';
+import 'utils/selector_utils.dart';
+
+void main() async {
+ late final GoRouter router;
+
+ setUpAll(() async {
+ router = buildAppRouter();
+ });
+
+ setUp(() async {
+ await registerDependencies(config: const AppConfig());
+ router.go(const DiscoveryRoute().location);
+ });
+
+ tearDown(() async {
+ await restartDependencies();
});
+
+ group(
+ 'Spaces drawer -',
+ () {
+ patrolWidgetTest(
+ 'visitor - no drawer button',
+ (PatrolTester $) async {
+ await $.pumpWidgetAndSettle(App(routerConfig: router));
+ await $(OverallSpacesPage.visitorShortcutBtn)
+ .tap(settleTimeout: const Duration(seconds: 10));
+ expect($(AppBarPage.spacesDrawerButton).exists, false);
+ },
+ );
+
+ patrolWidgetTest(
+ 'guest - chooser - clicking on icons works correctly',
+ (PatrolTester $) async {
+ await $.pumpWidgetAndSettle(App(routerConfig: router));
+ await $(OverallSpacesPage.guestShortcutBtn)
+ .tap(settleTimeout: const Duration(seconds: 10));
+ await $(AppBarPage.spacesDrawerButton).waitUntilVisible().tap();
+ SpacesDrawerPage.commonElementsLookAsExpected($);
+
+ // iterate thru spaces by clicking on spaces icons directly
+ for (final space in Space.values) {
+ await $(SpacesDrawerPage.chooserItem(space)).tap();
+ await SpacesDrawerPage.guestLooksAsExpected($, space);
+ }
+ SelectorUtils.isDisabled($, $(SpacesDrawerPage.chooserNextBtn));
+ },
+ );
+
+ patrolWidgetTest(
+ 'guest - chooser - next,previous buttons work correctly',
+ (PatrolTester $) async {
+ await $.pumpWidgetAndSettle(App(routerConfig: router));
+ await $(OverallSpacesPage.guestShortcutBtn)
+ .tap(settleTimeout: const Duration(seconds: 10));
+ await $(AppBarPage.spacesDrawerButton).waitUntilVisible().tap();
+
+ // iterate thru spaces by clicking next
+ for (final space in Space.values) {
+ await SpacesDrawerPage.guestLooksAsExpected($, space);
+ await $(SpacesDrawerPage.chooserNextBtn).tap();
+ SelectorUtils.isEnabled($, $(SpacesDrawerPage.chooserPrevBtn));
+ }
+ SelectorUtils.isDisabled($, $(SpacesDrawerPage.chooserNextBtn));
+
+ // iterate thru spaces by clicking previous
+ for (final space in Space.values.reversed) {
+ await SpacesDrawerPage.guestLooksAsExpected($, space);
+ await $(SpacesDrawerPage.chooserPrevBtn).tap();
+ SelectorUtils.isEnabled($, $(SpacesDrawerPage.chooserNextBtn));
+ }
+ SelectorUtils.isDisabled($, $(SpacesDrawerPage.chooserPrevBtn));
+ },
+ );
+
+ patrolWidgetTest(
+ 'user - chooser - clicking on icons works correctly',
+ (PatrolTester $) async {
+ await $.pumpWidgetAndSettle(App(routerConfig: router));
+ await $(OverallSpacesPage.userShortcutBtn)
+ .tap(settleTimeout: const Duration(seconds: 10));
+ await $(AppBarPage.spacesDrawerButton).waitUntilVisible().tap();
+ SpacesDrawerPage.commonElementsLookAsExpected($);
+ for (final space in Space.values) {
+ await $(SpacesDrawerPage.chooserItem(space)).tap();
+ await SpacesDrawerPage.userLooksAsExpected($, space);
+ }
+ },
+ );
+
+ patrolWidgetTest(
+ 'guest - chooser - all spaces button works',
+ (PatrolTester $) async {
+ await $.pumpWidgetAndSettle(App(routerConfig: router));
+ await $(OverallSpacesPage.guestShortcutBtn)
+ .tap(settleTimeout: const Duration(seconds: 10));
+ await $(AppBarPage.spacesDrawerButton).waitUntilVisible().tap();
+ await $(SpacesDrawerPage.allSpacesBtn).tap();
+ expect($(OverallSpacesPage.spacesListView), findsOneWidget);
+ },
+ );
+
+ patrolWidgetTest(
+ 'user - chooser - all spaces button works',
+ (PatrolTester $) async {
+ await $.pumpWidgetAndSettle(App(routerConfig: router));
+ await $(OverallSpacesPage.userShortcutBtn)
+ .tap(settleTimeout: const Duration(seconds: 10));
+ await $(AppBarPage.spacesDrawerButton).waitUntilVisible().tap();
+ await $(SpacesDrawerPage.allSpacesBtn).tap();
+ expect($(OverallSpacesPage.spacesListView), findsOneWidget);
+ },
+ );
+ },
+ );
}
diff --git a/catalyst_voices/apps/voices/integration_test/onboarding_test.dart b/catalyst_voices/apps/voices/integration_test/onboarding_test.dart
new file mode 100644
index 00000000000..af666e9739c
--- /dev/null
+++ b/catalyst_voices/apps/voices/integration_test/onboarding_test.dart
@@ -0,0 +1,52 @@
+import 'package:catalyst_voices/app/view/app.dart';
+import 'package:catalyst_voices/configs/bootstrap.dart';
+import 'package:catalyst_voices/routes/routes.dart';
+import 'package:catalyst_voices_models/catalyst_voices_models.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'package:go_router/go_router.dart';
+import 'package:patrol_finders/patrol_finders.dart';
+
+import 'pageobject/app_bar_page.dart';
+import 'pageobject/onboarding_page.dart';
+import 'pageobject/overall_spaces_page.dart';
+
+void main() async {
+ late final GoRouter router;
+
+ setUpAll(() async {
+ router = buildAppRouter();
+ });
+
+ setUp(() async {
+ await registerDependencies(config: const AppConfig());
+ router.go(const DiscoveryRoute().location);
+ });
+
+ tearDown(() async {
+ await restartDependencies();
+ });
+
+ group('Onboarding -', () {
+ patrolWidgetTest(
+ 'visitor - get started button works',
+ (PatrolTester $) async {
+ await $.pumpWidgetAndSettle(App(routerConfig: router));
+ await $(OverallSpacesPage.visitorShortcutBtn)
+ .tap(settleTimeout: const Duration(seconds: 10));
+ await $(AppBarPage.getStartedBtn).tap();
+ expect($(OnboardingPage.registrationInfoPanel), findsOneWidget);
+ expect($(OnboardingPage.registrationDetailsPanel), findsOneWidget);
+ },
+ );
+
+ patrolWidgetTest(
+ 'visitor - get started screen looks as expected',
+ (PatrolTester $) async {
+ await $.pumpWidgetAndSettle(App(routerConfig: router));
+ await $(AppBarPage.getStartedBtn)
+ .tap(settleTimeout: const Duration(seconds: 10));
+ await OnboardingPage.getStartedScreenLooksAsExpected($);
+ },
+ );
+ });
+}
diff --git a/catalyst_voices/apps/voices/integration_test/pageobject/app_bar_page.dart b/catalyst_voices/apps/voices/integration_test/pageobject/app_bar_page.dart
new file mode 100644
index 00000000000..ab5528f9136
--- /dev/null
+++ b/catalyst_voices/apps/voices/integration_test/pageobject/app_bar_page.dart
@@ -0,0 +1,8 @@
+library dashboard_page;
+
+import 'package:flutter/material.dart';
+
+class AppBarPage {
+ static const spacesDrawerButton = Key('DrawerButton');
+ static const getStartedBtn = Key('GetStartedButton');
+}
diff --git a/catalyst_voices/apps/voices/integration_test/pageobject/common_page.dart b/catalyst_voices/apps/voices/integration_test/pageobject/common_page.dart
new file mode 100644
index 00000000000..8581d62e1a4
--- /dev/null
+++ b/catalyst_voices/apps/voices/integration_test/pageobject/common_page.dart
@@ -0,0 +1,10 @@
+library dashboard_page;
+
+import 'package:flutter/material.dart';
+
+class CommonPage {
+ static const decoratorData = Key('DecoratorData');
+ static const decoratorIconBefore = Key('DecoratorIconBefore');
+ static const decoratorIconAfter = Key('DecoratorIconAfter');
+ static const dialogCloseButton = Key('DialogCloseButton');
+}
diff --git a/catalyst_voices/apps/voices/integration_test/pageobject/onboarding_page.dart b/catalyst_voices/apps/voices/integration_test/pageobject/onboarding_page.dart
new file mode 100644
index 00000000000..8b27bbfe509
--- /dev/null
+++ b/catalyst_voices/apps/voices/integration_test/pageobject/onboarding_page.dart
@@ -0,0 +1,159 @@
+library dashboard_page;
+
+import 'package:flutter/material.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'package:patrol_finders/patrol_finders.dart';
+
+import '../types/registration_state.dart';
+import '../utils/translations_utils.dart';
+import 'common_page.dart';
+
+class OnboardingPage {
+ static const registrationInfoPanel = Key('RegistrationInfoPanel');
+ static const registrationDetailsPanel = Key('RegistrationDetailsPanel');
+ static const registrationInfoLearnMoreButton = Key('LearnMoreButton');
+ static const headerTitle = Key('HeaderTitle');
+ static const headerSubtitle = Key('HeaderSubtitle');
+ static const headerBody = Key('HeaderBody');
+ static const registrationInfoPictureContainer = Key('PictureContainer');
+ static const registrationInfoTaskPicture = Key('TaskPictureIconBox');
+ static const registrationDetailsTitle = Key('RegistrationDetailsTitle');
+ static const registrationDetailsBody = Key('RegistrationDetailsBody');
+
+ static Future infoPartHeaderTitleText(PatrolTester $) async {
+ return $(registrationInfoPanel).$(headerTitle).text;
+ }
+
+ static Future infoPartHeaderSubtitleText(PatrolTester $) async {
+ return $(registrationInfoPanel).$(headerSubtitle).text;
+ }
+
+ static Future infoPartHeaderBodyText(PatrolTester $) async {
+ return $(registrationInfoPanel).$(headerBody).text;
+ }
+
+ static Future infoPartLearnMoreButtonText(PatrolTester $) async {
+ final child = find.descendant(
+ of: $(registrationInfoPanel).$(CommonPage.decoratorData),
+ matching: find.byType(Text),
+ );
+ return $(child).text;
+ }
+
+ static Finder infoPartTaskPicture(PatrolTester $) {
+ final child = find.descendant(
+ of: $(registrationInfoPanel).$(registrationInfoPictureContainer),
+ matching: find.byType(IconTheme),
+ );
+ return child;
+ }
+
+ static String? detailsPartGetStartedTitle(PatrolTester $) {
+ final child = find.descendant(
+ of: $(registrationDetailsPanel).$(registrationDetailsTitle),
+ matching: find.byType(Text),
+ );
+ return $(child).text;
+ }
+
+ static String? detailsPartGetStartedBody(PatrolTester $) {
+ final child = find.descendant(
+ of: $(registrationDetailsPanel).$(registrationDetailsBody),
+ matching: find.byType(Text),
+ );
+ return $(child).text;
+ }
+
+ static String? detailsPartGetStartedQuestionText(PatrolTester $) {
+ return $(registrationDetailsPanel).$(const Key('GetStartedQuestion')).text;
+ }
+
+ static Future detailsPartGetStartedCreateNewBtn(
+ PatrolTester $,
+ ) async {
+ return $(registrationDetailsPanel)
+ .$(const Key('CreateAccountType.createNew'));
+ }
+
+ static Future detailsPartGetStartedRecoverBtn(
+ PatrolTester $,
+ ) async {
+ return $(registrationDetailsPanel)
+ .$(const Key('CreateAccountType.recover'));
+ }
+
+ static Future getStartedScreenLooksAsExpected(PatrolTester $) async {
+ await registrationInfoPanelLooksAsExpected($, RegistrationState.getStarted);
+ await registrationDetailsPanelLooksAsExpected(
+ $,
+ RegistrationState.getStarted,
+ );
+ }
+
+ static Future registrationInfoPanelLooksAsExpected(
+ PatrolTester $,
+ RegistrationState step,
+ ) async {
+ switch (step) {
+ case RegistrationState.getStarted:
+ expect(await infoPartHeaderTitleText($), T.get('Get Started'));
+ expect(await infoPartLearnMoreButtonText($), T.get('Learn More'));
+ expect(infoPartTaskPicture($), findsOneWidget);
+ break;
+ case RegistrationState.checkYourKeychain:
+ throw UnimplementedError();
+ case RegistrationState.createKeychain:
+ throw UnimplementedError();
+ case RegistrationState.keychainCreated:
+ throw UnimplementedError();
+ case RegistrationState.keychainRestoreInfo:
+ throw UnimplementedError();
+ case RegistrationState.keychainRestoreInput:
+ throw UnimplementedError();
+ case RegistrationState.keychainRestoreStart:
+ throw UnimplementedError();
+ case RegistrationState.keychainRestoreSuccess:
+ throw UnimplementedError();
+ case RegistrationState.mnemonicInput:
+ throw UnimplementedError();
+ case RegistrationState.mnemonicVerified:
+ throw UnimplementedError();
+ case RegistrationState.mnemonicWritedown:
+ throw UnimplementedError();
+ case RegistrationState.passwordInfo:
+ throw UnimplementedError();
+ case RegistrationState.passwordInput:
+ throw UnimplementedError();
+ }
+ }
+
+ static Future registrationDetailsPanelLooksAsExpected(
+ PatrolTester $,
+ RegistrationState getStarted,
+ ) async {
+ expect(
+ detailsPartGetStartedTitle($),
+ T.get('Welcome to Catalyst'),
+ );
+ expect(
+ detailsPartGetStartedBody($),
+ isNotEmpty,
+ );
+ expect(
+ detailsPartGetStartedQuestionText($),
+ T.get('What do you want to do?'),
+ );
+ expect(
+ await detailsPartGetStartedCreateNewBtn($),
+ findsOneWidget,
+ );
+ expect(
+ await detailsPartGetStartedRecoverBtn($),
+ findsOneWidget,
+ );
+ expect(
+ $(CommonPage.dialogCloseButton),
+ findsOneWidget,
+ );
+ }
+}
diff --git a/catalyst_voices/apps/voices/integration_test/pageobject/overall_spaces_page.dart b/catalyst_voices/apps/voices/integration_test/pageobject/overall_spaces_page.dart
new file mode 100644
index 00000000000..6ee344a019c
--- /dev/null
+++ b/catalyst_voices/apps/voices/integration_test/pageobject/overall_spaces_page.dart
@@ -0,0 +1,15 @@
+library dashboard_page;
+
+import 'package:catalyst_voices_models/catalyst_voices_models.dart';
+import 'package:flutter/material.dart';
+
+class OverallSpacesPage {
+ static const guestShortcutBtn = Key('GuestShortcut');
+ static const visitorShortcutBtn = Key('VisitorShortcut');
+ static const userShortcutBtn = Key('UserShortcut');
+ static const spacesListView = Key('SpacesListView');
+
+ static Key spaceOverview(Space space) {
+ return Key('SpaceOverview.${space.name}');
+ }
+}
diff --git a/catalyst_voices/apps/voices/integration_test/pageobject/spaces_drawer_page.dart b/catalyst_voices/apps/voices/integration_test/pageobject/spaces_drawer_page.dart
new file mode 100644
index 00000000000..056d611b171
--- /dev/null
+++ b/catalyst_voices/apps/voices/integration_test/pageobject/spaces_drawer_page.dart
@@ -0,0 +1,159 @@
+library spaces_drawer_page;
+
+import 'package:catalyst_voices_models/catalyst_voices_models.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'package:patrol_finders/patrol_finders.dart';
+
+class SpacesDrawerPage {
+ static const closeBtn = Key('MenuCloseButton');
+ static const guestMenuItems = Key('GuestMenuItems');
+ static const allSpacesBtn = Key('DrawerChooserAllSpacesButton');
+ static const chooserPrevBtn = Key('DrawerChooserPreviousButton');
+ static const chooserNextBtn = Key('DrawerChooserNextButton');
+ static const chooserItemContainer = Key('DrawerChooserItem');
+ static const userDiscoveryDashboardTile = Key('DiscoveryDashboardTile');
+ static const userRolesTile = Key('RolesTile');
+ static const userFeedbackTile = Key('FeedbackTile');
+ static const userDocumentationTile = Key('DocumentationTile');
+ static const userDrawerMenuItem = Key('UserDrawerMenuItem');
+
+ static Key chooserItem(Space space) {
+ return Key('DrawerChooser$space');
+ }
+
+ static Key userHeader(Space space) {
+ return Key('SpaceHeader.${space.name}');
+ }
+
+ static Key chooserIcon(Space space) {
+ return Key('DrawerChooser${space}AvatarKey');
+ }
+
+ static Key userMenuContainer(Space space) {
+ return Key('Drawer${space}MenuKey');
+ }
+
+ static Key userSectionHeader(Space space) {
+ return Key('Header.${space.name}');
+ }
+
+ static void commonElementsLookAsExpected(PatrolTester $) {
+ expect($(closeBtn), findsOneWidget);
+ expect($(allSpacesBtn), findsOneWidget);
+ expect($(chooserPrevBtn), findsOneWidget);
+ expect($(chooserNextBtn), findsOneWidget);
+ expect($(chooserItemContainer), findsExactly(5));
+ }
+
+ static Future guestLooksAsExpected(PatrolTester $, Space space) async {
+ expect(
+ $(SpacesDrawerPage.chooserIcon(space)),
+ findsOneWidget,
+ );
+ final children = find.descendant(
+ of: $(guestMenuItems),
+ matching: find.byWidgetPredicate((widget) => true),
+ );
+ expect($(children), findsAtLeast(1));
+ }
+
+ static Future userLooksAsExpected(PatrolTester $, Space space) async {
+ switch (space) {
+ case Space.discovery:
+ userDiscoveryLooksAsExpected($);
+ break;
+ case Space.workspace:
+ userWorkspaceLooksAsExpected($);
+ break;
+ case Space.voting:
+ userVotingLooksAsExpected($);
+ break;
+ case Space.fundedProjects:
+ userFundedProjectsLooksAsExpected($);
+ break;
+ case Space.treasury:
+ userTreasuryLooksAsExpected($);
+ break;
+ }
+ }
+
+ static void userDiscoveryLooksAsExpected(PatrolTester $) {
+ expect(
+ $(userMenuContainer(Space.discovery)).$(userHeader(Space.discovery)),
+ findsOneWidget,
+ );
+ expect(
+ $(userMenuContainer(Space.discovery)).$(userDiscoveryDashboardTile),
+ findsOneWidget,
+ );
+ expect(
+ $(userMenuContainer(Space.discovery)).$(userRolesTile),
+ findsOneWidget,
+ );
+ expect(
+ $(userMenuContainer(Space.discovery)).$(userFeedbackTile),
+ findsOneWidget,
+ );
+ expect(
+ $(userMenuContainer(Space.discovery)).$(userDocumentationTile),
+ findsOneWidget,
+ );
+ }
+
+ static void userWorkspaceLooksAsExpected(PatrolTester $) {
+ expect(
+ $(userMenuContainer(Space.workspace)).$(userHeader(Space.workspace)),
+ findsOneWidget,
+ );
+ expect(
+ $(userMenuContainer(Space.workspace))
+ .$(userSectionHeader(Space.workspace)),
+ findsOneWidget,
+ );
+ final children = find.descendant(
+ of: $(userMenuContainer(Space.workspace)),
+ matching: $(userDrawerMenuItem),
+ );
+ expect($(children), findsAtLeast(1));
+ }
+
+ static void userVotingLooksAsExpected(PatrolTester $) {
+ expect(
+ $(userMenuContainer(Space.voting)).$(userHeader(Space.voting)),
+ findsOneWidget,
+ );
+ expect(
+ $(userMenuContainer(Space.voting)).$(userSectionHeader(Space.voting)),
+ findsOneWidget,
+ );
+ final children = find.descendant(
+ of: $(userMenuContainer(Space.voting)),
+ matching: $(userDrawerMenuItem),
+ );
+ expect($(children), findsAtLeast(1));
+ }
+
+ static void userFundedProjectsLooksAsExpected(PatrolTester $) {
+ expect(
+ $(userMenuContainer(Space.fundedProjects)),
+ findsOneWidget,
+ );
+ }
+
+ static void userTreasuryLooksAsExpected(PatrolTester $) {
+ expect(
+ $(userMenuContainer(Space.treasury)).$(userHeader(Space.treasury)),
+ findsOneWidget,
+ );
+ expect(
+ $(userMenuContainer(Space.treasury)).$(userSectionHeader(Space.treasury)),
+ findsOneWidget,
+ );
+ final children = find.descendant(
+ of: $(userMenuContainer(Space.treasury)),
+ matching: $(userDrawerMenuItem),
+ );
+ expect($(children), findsAtLeast(1));
+ }
+}
diff --git a/catalyst_voices/apps/voices/integration_test/types/registration_state.dart b/catalyst_voices/apps/voices/integration_test/types/registration_state.dart
new file mode 100644
index 00000000000..c40c7ddd5b6
--- /dev/null
+++ b/catalyst_voices/apps/voices/integration_test/types/registration_state.dart
@@ -0,0 +1,15 @@
+enum RegistrationState {
+ checkYourKeychain,
+ createKeychain,
+ getStarted,
+ keychainCreated,
+ keychainRestoreInfo,
+ keychainRestoreInput,
+ keychainRestoreStart,
+ keychainRestoreSuccess,
+ mnemonicInput,
+ mnemonicVerified,
+ mnemonicWritedown,
+ passwordInfo,
+ passwordInput;
+}
diff --git a/catalyst_voices/apps/voices/integration_test/utils/selector_utils.dart b/catalyst_voices/apps/voices/integration_test/utils/selector_utils.dart
new file mode 100644
index 00000000000..67a0c980078
--- /dev/null
+++ b/catalyst_voices/apps/voices/integration_test/utils/selector_utils.dart
@@ -0,0 +1,22 @@
+import 'package:flutter_test/flutter_test.dart';
+import 'package:patrol_finders/patrol_finders.dart';
+
+class SelectorUtils {
+ static void isDisabled(
+ PatrolTester $,
+ PatrolFinder widget, {
+ bool? reverse = false,
+ }) {
+ final widgetProps = $.tester.widget(widget).toString().split('(').last;
+ final expectedState = reverse! ? 'enabled' : 'disabled';
+ expect(
+ widgetProps.contains('disabled'),
+ !reverse,
+ reason: 'Expected $expectedState (${widget.description})',
+ );
+ }
+
+ static void isEnabled(PatrolTester $, PatrolFinder widget) {
+ isDisabled($, widget, reverse: true);
+ }
+}
diff --git a/catalyst_voices/apps/voices/integration_test/utils/translations_utils.dart b/catalyst_voices/apps/voices/integration_test/utils/translations_utils.dart
new file mode 100644
index 00000000000..3e409608a63
--- /dev/null
+++ b/catalyst_voices/apps/voices/integration_test/utils/translations_utils.dart
@@ -0,0 +1,8 @@
+//wrapper that we should adapt to read actual i18n translations we use in app
+//it will also support different locales once we have it
+//now this is here so we can easily replace this implementation and know where
+class T {
+ static String get(String key, {String? locale}) {
+ return key;
+ }
+}
diff --git a/catalyst_voices/apps/voices/lib/app/view/app.dart b/catalyst_voices/apps/voices/lib/app/view/app.dart
index cadb91549c8..9b5cc5a8f89 100644
--- a/catalyst_voices/apps/voices/lib/app/view/app.dart
+++ b/catalyst_voices/apps/voices/lib/app/view/app.dart
@@ -38,14 +38,26 @@ class _AppState extends State {
List _multiBlocProviders() {
return [
- BlocProvider(
- create: (_) => Dependencies.instance.get(),
- ),
- BlocProvider(
- create: (_) => Dependencies.instance.get(),
+ BlocProvider(
+ create: (_) => Dependencies.instance.get(),
),
BlocProvider(
- create: (_) => Dependencies.instance.get(),
+ create: (_) => Dependencies.instance.get(),
+ ),
+ BlocProvider(
+ create: (_) => Dependencies.instance.get(),
+ ),
+ BlocProvider(
+ create: (_) => Dependencies.instance.get(),
+ ),
+ BlocProvider(
+ create: (_) => Dependencies.instance.get(),
+ ),
+ BlocProvider(
+ create: (context) => Dependencies.instance.get(),
+ ),
+ BlocProvider(
+ create: (context) => Dependencies.instance.get(),
),
];
}
diff --git a/catalyst_voices/apps/voices/lib/app/view/app_active_state_listener.dart b/catalyst_voices/apps/voices/lib/app/view/app_active_state_listener.dart
new file mode 100644
index 00000000000..7a4ada05151
--- /dev/null
+++ b/catalyst_voices/apps/voices/lib/app/view/app_active_state_listener.dart
@@ -0,0 +1,49 @@
+import 'package:catalyst_voices/dependency/dependencies.dart';
+import 'package:catalyst_voices_services/catalyst_voices_services.dart';
+import 'package:flutter/material.dart';
+
+/// Observes application lifecycle and updates any dependencies that are
+/// interested in app state.
+class AppActiveStateListener extends StatefulWidget {
+ final Widget child;
+
+ const AppActiveStateListener({
+ super.key,
+ required this.child,
+ });
+
+ @override
+ State createState() => _AppActiveStateListenerState();
+}
+
+class _AppActiveStateListenerState extends State {
+ late final AppLifecycleListener _listener;
+
+ @override
+ void initState() {
+ super.initState();
+ _listener = AppLifecycleListener(
+ onResume: _handleResumed,
+ onInactive: _handleInactive,
+ );
+ }
+
+ @override
+ void dispose() {
+ _listener.dispose();
+ super.dispose();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return widget.child;
+ }
+
+ Future _handleResumed() async {
+ Dependencies.instance.get().isActive = true;
+ }
+
+ Future _handleInactive() async {
+ Dependencies.instance.get().isActive = false;
+ }
+}
diff --git a/catalyst_voices/apps/voices/lib/app/view/app_content.dart b/catalyst_voices/apps/voices/lib/app/view/app_content.dart
index be743c669a2..d27d3ca5844 100644
--- a/catalyst_voices/apps/voices/lib/app/view/app_content.dart
+++ b/catalyst_voices/apps/voices/lib/app/view/app_content.dart
@@ -1,3 +1,4 @@
+import 'package:catalyst_voices/app/view/app_active_state_listener.dart';
import 'package:catalyst_voices/app/view/app_precache_image_assets.dart';
import 'package:catalyst_voices/app/view/app_session_listener.dart';
import 'package:catalyst_voices_brands/catalyst_voices_brands.dart';
@@ -51,9 +52,15 @@ class AppContentState extends State {
brightness: Brightness.dark,
),
builder: (context, child) {
- return GlobalPrecacheImages(
- child: GlobalSessionListener(
- child: child ?? const SizedBox.shrink(),
+ return Scaffold(
+ primary: false,
+ backgroundColor: Colors.transparent,
+ body: AppActiveStateListener(
+ child: GlobalPrecacheImages(
+ child: GlobalSessionListener(
+ child: child ?? const SizedBox.shrink(),
+ ),
+ ),
),
);
},
diff --git a/catalyst_voices/apps/voices/lib/common/codecs/markdown_codec.dart b/catalyst_voices/apps/voices/lib/common/codecs/markdown_codec.dart
new file mode 100644
index 00000000000..08081267f70
--- /dev/null
+++ b/catalyst_voices/apps/voices/lib/common/codecs/markdown_codec.dart
@@ -0,0 +1,60 @@
+import 'dart:convert';
+
+import 'package:catalyst_voices_models/catalyst_voices_models.dart';
+import 'package:flutter_quill/quill_delta.dart';
+import 'package:markdown/markdown.dart' as md;
+import 'package:markdown_quill/markdown_quill.dart';
+
+// Note.
+// This codec is here because it depends on flutter_quill which is heavy
+// package with lots different dependencies which we don't want to have in
+// other packages.
+//
+// If we could have just Delta package it would be preferred to live in
+// models/shared package
+const markdown = MarkdownCodec();
+
+final _mdDocument = md.Document();
+final _mdToDelta = MarkdownToDelta(markdownDocument: _mdDocument);
+final _deltaToMd = DeltaToMarkdown(
+ customContentHandler: DeltaToMarkdown.escapeSpecialCharactersRelaxed,
+);
+
+final class MarkdownCodec extends Codec {
+ const MarkdownCodec();
+
+ @override
+ Converter get decoder => const MarkdownEncoder();
+
+ @override
+ Converter get encoder => const MarkdownDecoder();
+}
+
+class MarkdownDecoder extends Converter {
+ const MarkdownDecoder();
+
+ @override
+ Delta convert(MarkdownData input) {
+ if (input.data.isEmpty) {
+ return Delta();
+ }
+
+ return _mdToDelta.convert(input.data);
+ }
+}
+
+class MarkdownEncoder extends Converter {
+ const MarkdownEncoder();
+
+ @override
+ MarkdownData convert(Delta input) {
+ if (input.isEmpty) {
+ return const MarkdownData('');
+ }
+
+ final data = _deltaToMd.convert(input);
+ final trimmed = data.trim();
+
+ return MarkdownData(trimmed);
+ }
+}
diff --git a/catalyst_voices/apps/voices/lib/common/ext/guidance_ext.dart b/catalyst_voices/apps/voices/lib/common/ext/guidance_ext.dart
index e4ab1f54554..1a59ca68baa 100644
--- a/catalyst_voices/apps/voices/lib/common/ext/guidance_ext.dart
+++ b/catalyst_voices/apps/voices/lib/common/ext/guidance_ext.dart
@@ -1,6 +1,6 @@
import 'package:catalyst_voices_assets/catalyst_voices_assets.dart';
import 'package:catalyst_voices_localization/generated/catalyst_voices_localizations.dart';
-import 'package:catalyst_voices_view_models/catalyst_voices_view_models.dart';
+import 'package:catalyst_voices_models/catalyst_voices_models.dart';
extension GuidanceExt on GuidanceType {
String localizedType(VoicesLocalizations localizations) => switch (this) {
diff --git a/catalyst_voices/apps/voices/lib/common/ext/map_ext.dart b/catalyst_voices/apps/voices/lib/common/ext/map_ext.dart
new file mode 100644
index 00000000000..12e141efde7
--- /dev/null
+++ b/catalyst_voices/apps/voices/lib/common/ext/map_ext.dart
@@ -0,0 +1,7 @@
+extension MapFilterExtension on Map {
+ Map useKeys(List keys) {
+ return Map.fromEntries(
+ entries.where((entry) => keys.contains(entry.key)),
+ );
+ }
+}
diff --git a/catalyst_voices/apps/voices/lib/common/ext/time_of_day_ext.dart b/catalyst_voices/apps/voices/lib/common/ext/time_of_day_ext.dart
new file mode 100644
index 00000000000..8bd65d9a602
--- /dev/null
+++ b/catalyst_voices/apps/voices/lib/common/ext/time_of_day_ext.dart
@@ -0,0 +1,10 @@
+import 'package:flutter/material.dart';
+
+extension TimeOfDayExt on TimeOfDay {
+ String get formatted {
+ final hour = this.hour.toString().padLeft(2, '0');
+ final minute = this.minute.toString().padLeft(2, '0');
+
+ return '$hour:$minute';
+ }
+}
diff --git a/catalyst_voices/apps/voices/lib/common/formatters/date_formatter.dart b/catalyst_voices/apps/voices/lib/common/formatters/date_formatter.dart
index 0829da4ce11..74ee6f28bb5 100644
--- a/catalyst_voices/apps/voices/lib/common/formatters/date_formatter.dart
+++ b/catalyst_voices/apps/voices/lib/common/formatters/date_formatter.dart
@@ -27,4 +27,72 @@ abstract class DateFormatter {
return DateFormat.yMMMMd().format(dateTime);
}
+
+ static String formatInDays(
+ VoicesLocalizations l10n,
+ DateTime dateTime, {
+ DateTime? from,
+ }) {
+ from ??= DateTimeExt.now();
+
+ final days = dateTime.isAfter(from) ? dateTime.difference(from).inDays : 0;
+
+ return l10n.inXDays(days);
+ }
+
+ static (String date, String time) formatDateTimeParts(
+ DateTime date,
+ ) {
+ final dayMonthFormatter = DateFormat('d MMMM').format(date);
+ final timeFormatter = DateFormat('HH:mm').format(date);
+
+ return (dayMonthFormatter, timeFormatter);
+ }
+
+ static String formatShortMonth(
+ VoicesLocalizations l10n,
+ DateTime dateTime,
+ ) {
+ return DateFormat.MMM().format(dateTime);
+ }
+
+ /// Formats full date and time.
+ /// If [timeOnNewline] is true then the time will be placed on a new line.
+ ///
+ /// Example:
+ /// - Thu, 6 June 2024 10:00 am
+ static String formatFullDateTime(
+ DateTime dateTime, {
+ bool timeOnNewline = false,
+ }) {
+ final format =
+ timeOnNewline ? 'EEE, d MMMM yyyy\nh:mm a' : 'EEE, d MMMM yyyy h:mm a';
+ return DateFormat(format).format(dateTime);
+ }
+
+ /// Formats the timezone info extracted from the [dateTime].
+ ///
+ /// Example:
+ /// - GMT+01:00 Central European Standard Time
+ static String formatTimezone(DateTime dateTime) {
+ final offset = _formatTimezoneOffset(dateTime.timeZoneOffset);
+ final timezone = dateTime.timeZoneName;
+ return 'GMT$offset $timezone';
+ }
+
+ static String _formatTimezoneOffset(Duration offset) {
+ if (offset.isNegative) {
+ return '-${_formatDurationHHmm(offset)}';
+ } else {
+ return '+${_formatDurationHHmm(offset)}';
+ }
+ }
+
+ static String _formatDurationHHmm(Duration offset) {
+ final nf = NumberFormat('00');
+ final hours = offset.inHours;
+ final minutes = offset.inMinutes - hours * Duration.minutesPerHour;
+
+ return '${nf.format(hours)}:${nf.format(minutes)}';
+ }
}
diff --git a/catalyst_voices/apps/voices/lib/configs/bootstrap.dart b/catalyst_voices/apps/voices/lib/configs/bootstrap.dart
index 764087cb9dc..05578a7c649 100644
--- a/catalyst_voices/apps/voices/lib/configs/bootstrap.dart
+++ b/catalyst_voices/apps/voices/lib/configs/bootstrap.dart
@@ -7,6 +7,9 @@ import 'package:catalyst_voices/configs/sentry_service.dart';
import 'package:catalyst_voices/dependency/dependencies.dart';
import 'package:catalyst_voices/routes/guards/milestone_guard.dart';
import 'package:catalyst_voices/routes/routes.dart';
+import 'package:catalyst_voices_models/catalyst_voices_models.dart';
+import 'package:catalyst_voices_repositories/catalyst_voices_repositories.dart';
+import 'package:catalyst_voices_services/catalyst_voices_services.dart';
import 'package:catalyst_voices_shared/catalyst_voices_shared.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
@@ -74,6 +77,30 @@ Future _doBootstrapAndRun(BootstrapWidgetBuilder builder) async {
await _runApp(app);
}
+@visibleForTesting
+GoRouter buildAppRouter({
+ String? initialLocation,
+}) {
+ return AppRouter.init(
+ initialLocation: initialLocation,
+ guards: const [
+ MilestoneGuard(),
+ ],
+ );
+}
+
+@visibleForTesting
+Future registerDependencies({required AppConfig config}) async {
+ if (!Dependencies.instance.isInitialized) {
+ await Dependencies.instance.init(config: config);
+ }
+}
+
+@visibleForTesting
+Future restartDependencies() async {
+ await Dependencies.instance.reset;
+}
+
/// Initializes the application before it can be run. Should setup all
/// the things which are necessary before the actual app is run,
/// either via [runApp] or injected into a test environment during
@@ -81,7 +108,9 @@ Future _doBootstrapAndRun(BootstrapWidgetBuilder builder) async {
///
/// Initialization logic that is relevant for [runApp] scenario
/// only should be added to [_doBootstrapAndRun], not here.
-Future bootstrap() async {
+Future bootstrap({
+ GoRouter? router,
+}) async {
_loggingService
..level = kDebugMode ? Level.FINER : Level.OFF
..printLogs = kDebugMode;
@@ -89,16 +118,17 @@ Future bootstrap() async {
GoRouter.optionURLReflectsImperativeAPIs = true;
setPathUrlStrategy();
- await Dependencies.instance.init();
+ final configService = ConfigService(ConfigRepository());
+ final config = await configService
+ .getAppConfig()
+ .onError((error, stackTrace) => const AppConfig());
+
+ await registerDependencies(config: config);
// Key derivation needs to be initialized before it can be used
await CatalystKeyDerivation.init();
- final router = AppRouter.init(
- guards: const [
- MilestoneGuard(),
- ],
- );
+ router ??= buildAppRouter();
Bloc.observer = AppBlocObserver();
diff --git a/catalyst_voices/apps/voices/lib/dependency/dependencies.dart b/catalyst_voices/apps/voices/lib/dependency/dependencies.dart
index e93ed705f77..9bfd7421253 100644
--- a/catalyst_voices/apps/voices/lib/dependency/dependencies.dart
+++ b/catalyst_voices/apps/voices/lib/dependency/dependencies.dart
@@ -3,33 +3,52 @@ import 'dart:async';
import 'package:catalyst_cardano/catalyst_cardano.dart';
import 'package:catalyst_key_derivation/catalyst_key_derivation.dart';
import 'package:catalyst_voices_blocs/catalyst_voices_blocs.dart';
+import 'package:catalyst_voices_models/catalyst_voices_models.dart';
import 'package:catalyst_voices_repositories/catalyst_voices_repositories.dart';
import 'package:catalyst_voices_services/catalyst_voices_services.dart';
import 'package:catalyst_voices_shared/catalyst_voices_shared.dart';
+import 'package:catalyst_voices_view_models/catalyst_voices_view_models.dart';
+import 'package:flutter_secure_storage/flutter_secure_storage.dart';
+import 'package:shared_preferences/shared_preferences.dart';
final class Dependencies extends DependencyProvider {
static final Dependencies instance = Dependencies._();
+ bool _isInitialized = false;
+
Dependencies._();
- Future init() async {
+ Future init({
+ required AppConfig config,
+ }) async {
DependencyProvider.instance = this;
+
+ registerSingleton(config);
+
+ _registerStorages();
_registerServices();
_registerRepositories();
_registerBlocsWithDependencies();
+
+ _isInitialized = true;
+ }
+
+ bool get isInitialized => _isInitialized;
+
+ @override
+ Future get reset {
+ return super.reset.whenComplete(() {
+ _isInitialized = false;
+ });
}
void _registerBlocsWithDependencies() {
this
- ..registerSingleton(
- AuthenticationBloc(
- authenticationRepository: get(),
- ),
+ ..registerLazySingleton(
+ AdminToolsCubit.new,
)
- ..registerLazySingleton(
- () => LoginBloc(
- authenticationRepository: get(),
- ),
+ ..registerLazySingleton(
+ () => get(),
)
..registerLazySingleton(
() {
@@ -37,6 +56,8 @@ final class Dependencies extends DependencyProvider {
get(),
get(),
get(),
+ get(),
+ get(),
);
},
dispose: (cubit) async => cubit.close(),
@@ -49,31 +70,70 @@ final class Dependencies extends DependencyProvider {
registrationService: get(),
progressNotifier: get(),
);
+ })
+ ..registerLazySingleton(
+ () => ProposalsCubit(
+ get(),
+ get(),
+ get(),
+ ),
+ )
+ ..registerFactory(() {
+ return CampaignDetailsBloc(
+ get(),
+ );
+ })
+ ..registerLazySingleton(() {
+ return CampaignInfoCubit(
+ get(),
+ get(),
+ );
+ })
+ // TODO(ryszard-schossler): add repository for campaign management
+ ..registerLazySingleton(
+ CampaignBuilderCubit.new,
+ )
+ ..registerFactory(() {
+ return WorkspaceBloc(
+ get(),
+ );
+ })
+ ..registerFactory(() {
+ return ProposalBuilderBloc(
+ get(),
+ );
});
}
void _registerRepositories() {
this
- ..registerLazySingleton(
- () => CredentialsStorageRepository(storage: get()),
- )
- ..registerLazySingleton(
- () => AuthenticationRepository(credentialsStorageRepository: get()),
- )
..registerLazySingleton(
TransactionConfigRepository.new,
- );
+ )
+ ..registerLazySingleton(ProposalRepository.new)
+ ..registerLazySingleton(CampaignRepository.new)
+ ..registerLazySingleton(ConfigRepository.new)
+ ..registerLazySingleton(() {
+ return UserRepository(
+ get(),
+ get(),
+ );
+ });
}
void _registerServices() {
registerLazySingleton(() => const SecureStorage());
registerLazySingleton(CatalystKeyDerivation.new);
registerLazySingleton(() => KeyDerivation(get()));
- registerLazySingleton(VaultKeychainProvider.new);
- registerLazySingleton(SecureDummyAuthStorage.new);
+ registerLazySingleton(() {
+ return VaultKeychainProvider(
+ secureStorage: get(),
+ sharedPreferences: get(),
+ cacheConfig: get().cache,
+ );
+ });
registerLazySingleton(Downloader.new);
registerLazySingleton(() => CatalystCardano.instance);
- registerLazySingleton(SecureUserStorage.new);
registerLazySingleton(
RegistrationProgressNotifier.new,
);
@@ -88,11 +148,32 @@ final class Dependencies extends DependencyProvider {
registerLazySingleton(
() {
return UserService(
- keychainProvider: get(),
- userStorage: get(),
+ userRepository: get(),
);
},
dispose: (service) => unawaited(service.dispose()),
);
+ registerLazySingleton(AccessControl.new);
+ registerLazySingleton(() {
+ return CampaignService(
+ get(),
+ );
+ });
+ registerLazySingleton(() {
+ return ProposalService(
+ get(),
+ );
+ });
+ registerLazySingleton(() {
+ return ConfigService(
+ get(),
+ );
+ });
+ }
+
+ void _registerStorages() {
+ registerLazySingleton(FlutterSecureStorage.new);
+ registerLazySingleton(SharedPreferencesAsync.new);
+ registerLazySingleton(SecureUserStorage.new);
}
}
diff --git a/catalyst_voices/apps/voices/lib/pages/account/unlock_keychain_dialog.dart b/catalyst_voices/apps/voices/lib/pages/account/unlock_keychain_dialog.dart
index 2c3b3385e45..deb0a32412e 100644
--- a/catalyst_voices/apps/voices/lib/pages/account/unlock_keychain_dialog.dart
+++ b/catalyst_voices/apps/voices/lib/pages/account/unlock_keychain_dialog.dart
@@ -155,6 +155,7 @@ class _UnlockPassword extends StatelessWidget {
Widget build(BuildContext context) {
return VoicesPasswordTextField(
controller: controller,
+ autofocus: true,
decoration: VoicesTextFieldDecoration(
labelText: context.l10n.unlockDialogHint,
errorText: error?.message(context),
diff --git a/catalyst_voices/apps/voices/lib/pages/campaign/admin_tools/campaign_admin_tools_dialog.dart b/catalyst_voices/apps/voices/lib/pages/campaign/admin_tools/campaign_admin_tools_dialog.dart
new file mode 100644
index 00000000000..c83dd1977db
--- /dev/null
+++ b/catalyst_voices/apps/voices/lib/pages/campaign/admin_tools/campaign_admin_tools_dialog.dart
@@ -0,0 +1,348 @@
+import 'package:catalyst_voices/common/ext/space_ext.dart';
+import 'package:catalyst_voices/pages/campaign/admin_tools/campaign_admin_tools_events.dart';
+import 'package:catalyst_voices/pages/campaign/admin_tools/campaign_admin_tools_views.dart';
+import 'package:catalyst_voices/widgets/widgets.dart';
+import 'package:catalyst_voices_assets/catalyst_voices_assets.dart';
+import 'package:catalyst_voices_blocs/catalyst_voices_blocs.dart';
+import 'package:catalyst_voices_brands/catalyst_voices_brands.dart';
+import 'package:catalyst_voices_localization/catalyst_voices_localization.dart';
+import 'package:catalyst_voices_models/catalyst_voices_models.dart';
+import 'package:catalyst_voices_shared/catalyst_voices_shared.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+/// A draggable [CampaignAdminToolsDialog],
+/// should be used as a child of a [Stack].
+///
+/// Initially shown at bottom-left corner with [initialOffset] offset.
+class DraggableCampaignAdminToolsDialog extends StatefulWidget {
+ /// The key for the [CampaignAdminToolsDialog] to make sure it's state
+ /// is kept when a user keeps dragging it.
+ ///
+ /// The state might include currently open tab from [TabBar],
+ /// scroll position, etc.
+ final GlobalKey dialogKey;
+
+ /// See [CampaignAdminToolsDialog.selectedSpace].
+ final Space selectedSpace;
+
+ /// See [CampaignAdminToolsDialog.onSpaceSelected].
+ final ValueChanged onSpaceSelected;
+
+ /// The initial offset from bottom-left for the dialog.
+ final Offset initialOffset;
+
+ const DraggableCampaignAdminToolsDialog({
+ super.key,
+ required this.dialogKey,
+ required this.selectedSpace,
+ required this.onSpaceSelected,
+ this.initialOffset = const Offset(32, 32),
+ });
+
+ @override
+ State createState() =>
+ _DraggableCampaignAdminToolsDialogState();
+}
+
+class _DraggableCampaignAdminToolsDialogState
+ extends State {
+ Offset _position = Offset.infinite;
+ late Size _screenSize;
+
+ @override
+ void didChangeDependencies() {
+ super.didChangeDependencies();
+
+ _screenSize = MediaQuery.sizeOf(context);
+
+ if (_position.isInfinite) {
+ // initialize it for the first time
+ _position = Offset(
+ widget.initialOffset.dx,
+ _screenSize.height -
+ CampaignAdminToolsDialog._height -
+ widget.initialOffset.dy,
+ );
+ } else {
+ // clamp it so that it fits into the screen
+ // in case user shrinks the app window
+
+ _position = _clampIntoScreenBounds(_position);
+ }
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ final Widget child = CampaignAdminToolsDialog(
+ key: widget.dialogKey,
+ selectedSpace: widget.selectedSpace,
+ onSpaceSelected: widget.onSpaceSelected,
+ );
+
+ return Positioned(
+ left: _position.dx,
+ top: _position.dy,
+ child: Draggable(
+ onDragUpdate: _onDragUpdate,
+ childWhenDragging: const Offstage(),
+ feedback: child,
+ child: child,
+ ),
+ );
+ }
+
+ void _onDragUpdate(DragUpdateDetails details) {
+ final newPosition = _position + details.delta;
+ final clampedPosition = _clampIntoScreenBounds(newPosition);
+
+ if (_position != clampedPosition) {
+ setState(() {
+ _position = clampedPosition;
+ });
+ }
+ }
+
+ /// Makes sure the dialog would fit into a screen window
+ /// even if the window gets shrunk, etc.
+ Offset _clampIntoScreenBounds(Offset offset) {
+ return Offset(
+ offset.dx.clamp(
+ 0,
+ _screenSize.width - CampaignAdminToolsDialog._width,
+ ),
+ offset.dy.clamp(
+ 0,
+ _screenSize.height - CampaignAdminToolsDialog._height,
+ ),
+ );
+ }
+}
+
+/// The campaign admin tools dialog which supports
+/// mocking different campaign and user states.
+///
+/// With it you can mock the keychain, mock the
+/// campaign state or quickly switch between states.
+class CampaignAdminToolsDialog extends StatelessWidget {
+ /// The keyboard shortcut to activate the admin tools.
+ ///
+ /// You must handle the shortcut in the parent widget,
+ /// it is added here for convenience.
+ static final ShortcutActivator shortcut = LogicalKeySet(
+ LogicalKeyboardKey.control,
+ LogicalKeyboardKey.shift,
+ LogicalKeyboardKey.keyA,
+ );
+
+ static const double _width = 360;
+ static const double _height = 480;
+
+ /// The current selected [Space].
+ /// Admin tools reuse the currently selected space from the navigation drawer.
+ final Space selectedSpace;
+
+ /// Callback to notify when [Space] changes.
+ /// In response to this event the app should navigate to given space.
+ final ValueChanged onSpaceSelected;
+
+ const CampaignAdminToolsDialog({
+ super.key,
+ required this.selectedSpace,
+ required this.onSpaceSelected,
+ });
+
+ @override
+ Widget build(BuildContext context) {
+ return Container(
+ width: _width,
+ height: _height,
+ clipBehavior: Clip.antiAlias,
+ decoration: BoxDecoration(
+ color: Theme.of(context).colors.elevationsOnSurfaceNeutralLv1White,
+ borderRadius: BorderRadius.circular(16),
+ border: Border.all(
+ color: Theme.of(context).colors.onSurfaceNeutral012!,
+ width: 1,
+ ),
+ ),
+ child: Material(
+ type: MaterialType.transparency,
+ child: Column(
+ children: [
+ const _Header(),
+ const Expanded(child: _Tabs()),
+ _BlocFooter(
+ selectedSpace: selectedSpace,
+ onSpaceSelected: onSpaceSelected,
+ ),
+ ],
+ ),
+ ),
+ );
+ }
+}
+
+class _Header extends StatelessWidget {
+ const _Header();
+
+ @override
+ Widget build(BuildContext context) {
+ return Padding(
+ padding: const EdgeInsets.fromLTRB(24, 12, 12, 12),
+ child: Row(
+ children: [
+ Expanded(
+ child: Text(
+ context.l10n.campaignPreviewTitle,
+ style: Theme.of(context).textTheme.titleMedium,
+ ),
+ ),
+ XButton(
+ onTap: () => context.read().disable(),
+ ),
+ ],
+ ),
+ );
+ }
+}
+
+class _Tabs extends StatelessWidget {
+ const _Tabs();
+
+ @override
+ Widget build(BuildContext context) {
+ return const DefaultTabController(
+ length: 2,
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ _TabBar(),
+ Expanded(
+ child: TabBarStackView(
+ children: [
+ CampaignAdminToolsEventsTab(),
+ CampaignAdminToolsViewsTab(),
+ ],
+ ),
+ ),
+ ],
+ ),
+ );
+ }
+}
+
+class _TabBar extends StatelessWidget {
+ const _TabBar();
+
+ @override
+ Widget build(BuildContext context) {
+ return TabBar(
+ tabAlignment: TabAlignment.fill,
+ indicatorSize: TabBarIndicatorSize.tab,
+ tabs: [
+ Tab(
+ text: context.l10n.campaignPreviewEvents,
+ ),
+ Tab(
+ text: context.l10n.campaignPreviewViews,
+ ),
+ ],
+ );
+ }
+}
+
+class _BlocFooter extends StatelessWidget {
+ final Space selectedSpace;
+ final ValueChanged onSpaceSelected;
+
+ const _BlocFooter({
+ required this.selectedSpace,
+ required this.onSpaceSelected,
+ });
+
+ @override
+ Widget build(BuildContext context) {
+ return BlocSelector>(
+ selector: (state) => state.spaces,
+ builder: (context, spaces) {
+ return Offstage(
+ // don't show footer with spaces if there's only once,
+ // since the user can't change it to anything else
+ offstage: spaces.length <= 1,
+ child: _Footer(
+ selectedSpace: selectedSpace,
+ onSpaceSelected: onSpaceSelected,
+ ),
+ );
+ },
+ );
+ }
+}
+
+class _Footer extends StatelessWidget {
+ final Space selectedSpace;
+ final ValueChanged onSpaceSelected;
+
+ const _Footer({
+ required this.selectedSpace,
+ required this.onSpaceSelected,
+ });
+
+ @override
+ Widget build(BuildContext context) {
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.stretch,
+ children: [
+ const Divider(
+ height: 0,
+ indent: 0,
+ endIndent: 0,
+ ),
+ Padding(
+ padding: const EdgeInsets.all(12),
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ for (final space in Space.values)
+ _SpaceItem(
+ space: space,
+ isActive: space == selectedSpace,
+ onTap: () => onSpaceSelected(space),
+ ),
+ ].separatedBy(const SizedBox(width: 8)).toList(),
+ ),
+ ),
+ ],
+ );
+ }
+}
+
+class _SpaceItem extends StatelessWidget {
+ final Space space;
+ final bool isActive;
+ final VoidCallback onTap;
+
+ const _SpaceItem({
+ required this.space,
+ required this.isActive,
+ required this.onTap,
+ });
+
+ @override
+ Widget build(BuildContext context) {
+ return VoicesAvatar(
+ icon: space.icon.buildIcon(),
+ backgroundColor:
+ isActive ? space.backgroundColor(context) : Colors.transparent,
+ foregroundColor: isActive
+ ? space.foregroundColor(context)
+ : Theme.of(context).colors.iconsForeground,
+ padding: const EdgeInsets.all(8),
+ radius: 20,
+ onTap: onTap,
+ );
+ }
+}
diff --git a/catalyst_voices/apps/voices/lib/pages/campaign/admin_tools/campaign_admin_tools_events.dart b/catalyst_voices/apps/voices/lib/pages/campaign/admin_tools/campaign_admin_tools_events.dart
new file mode 100644
index 00000000000..f6ccff21016
--- /dev/null
+++ b/catalyst_voices/apps/voices/lib/pages/campaign/admin_tools/campaign_admin_tools_events.dart
@@ -0,0 +1,354 @@
+import 'dart:async';
+
+import 'package:catalyst_voices/pages/campaign/admin_tools/campaign_admin_tools_dialog.dart';
+import 'package:catalyst_voices/widgets/buttons/voices_text_button.dart';
+import 'package:catalyst_voices_assets/catalyst_voices_assets.dart';
+import 'package:catalyst_voices_blocs/catalyst_voices_blocs.dart';
+import 'package:catalyst_voices_brands/catalyst_voices_brands.dart';
+import 'package:catalyst_voices_localization/catalyst_voices_localization.dart';
+import 'package:catalyst_voices_shared/catalyst_voices_shared.dart';
+import 'package:catalyst_voices_view_models/catalyst_voices_view_models.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+/// The "events" tab of the [CampaignAdminToolsDialog].
+class CampaignAdminToolsEventsTab extends StatefulWidget {
+ const CampaignAdminToolsEventsTab({super.key});
+
+ @override
+ State createState() =>
+ _CampaignAdminToolsEventsTabState();
+}
+
+class _CampaignAdminToolsEventsTabState
+ extends State {
+ static const _defaultStageTransitionDelay = Duration(seconds: 5);
+
+ Timer? _stageTimer;
+ DateTime? _stageTransitionAt;
+ Duration _stageTransitionDelay = _defaultStageTransitionDelay;
+
+ @override
+ void dispose() {
+ _stageTimer?.cancel();
+ super.dispose();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return BlocSelector(
+ selector: (state) => state.campaignStage,
+ builder: (context, stage) {
+ return Column(
+ children: [
+ Expanded(
+ child: _CampaignStatusChooser(
+ selectedStage: stage,
+ onStageSelected: _onStageSelected,
+ ),
+ ),
+ _EventTimelapseControls(
+ nextStageTransitionAt: _stageTransitionAt,
+ stageTransitionDelay: _stageTransitionDelay,
+ onPreviousStage: _canSelectPreviousStage(stage)
+ ? () => _onPreviousStage(stage)
+ : null,
+ onNextStage:
+ _canSelectNextStage(stage) ? () => _onNextStage(stage) : null,
+ onTransitionDelayChanged: _onTransitionDelayChanged,
+ ),
+ ],
+ );
+ },
+ );
+ }
+
+ void _onStageSelected(CampaignStage stage) {
+ setState(() {
+ _stageTimer?.cancel();
+ _stageTimer = Timer(
+ _stageTransitionDelay,
+ () => _updateStage(stage),
+ );
+ _stageTransitionAt = DateTimeExt.now().add(_stageTransitionDelay);
+ });
+ }
+
+ bool _canSelectPreviousStage(CampaignStage currentStage) {
+ // draft stage is not supported
+
+ final previousIndex = currentStage.index - 1;
+ return previousIndex > CampaignStage.draft.index;
+ }
+
+ bool _canSelectNextStage(CampaignStage currentStage) {
+ final nextIndex = currentStage.index + 1;
+ return nextIndex < CampaignStage.values.length;
+ }
+
+ void _onPreviousStage(CampaignStage currentStage) {
+ if (!_canSelectPreviousStage(currentStage)) return;
+
+ _onStageSelected(CampaignStage.values[currentStage.index - 1]);
+ }
+
+ void _onNextStage(CampaignStage currentStage) {
+ if (!_canSelectNextStage(currentStage)) return;
+
+ _onStageSelected(CampaignStage.values[currentStage.index + 1]);
+ }
+
+ void _updateStage(CampaignStage stage) {
+ context.read().updateCampaignStage(stage);
+
+ setState(() {
+ _stageTransitionAt = null;
+ });
+ }
+
+ void _onTransitionDelayChanged(Duration delay) {
+ setState(() {
+ _stageTransitionDelay = delay;
+ });
+ }
+}
+
+class _CampaignStatusChooser extends StatelessWidget {
+ final CampaignStage selectedStage;
+ final ValueChanged onStageSelected;
+
+ const _CampaignStatusChooser({
+ required this.selectedStage,
+ required this.onStageSelected,
+ });
+
+ @override
+ Widget build(BuildContext context) {
+ return Material(
+ color: Theme.of(context).colors.elevationsOnSurfaceNeutralLv1Grey,
+ child: Column(
+ children: [
+ const SizedBox(height: 8),
+ for (final stage in CampaignStage.values)
+ if (stage != CampaignStage.draft)
+ _EventItem(
+ stage: stage,
+ isActive: stage == selectedStage,
+ onTap: () => onStageSelected(stage),
+ ),
+ const SizedBox(height: 8),
+ ],
+ ),
+ );
+ }
+}
+
+class _EventItem extends StatelessWidget {
+ final CampaignStage stage;
+ final bool isActive;
+ final VoidCallback onTap;
+
+ const _EventItem({
+ required this.stage,
+ required this.isActive,
+ required this.onTap,
+ });
+
+ @override
+ Widget build(BuildContext context) {
+ final color = isActive
+ ? Theme.of(context).colorScheme.primary
+ : Theme.of(context).colors.textOnPrimary;
+
+ return InkWell(
+ onTap: onTap,
+ child: Padding(
+ padding: const EdgeInsets.fromLTRB(16, 12, 24, 12),
+ child: Row(
+ children: [
+ _icon.buildIcon(
+ size: 24,
+ color: color,
+ ),
+ const SizedBox(width: 16),
+ Expanded(
+ child: Text(
+ _text(context.l10n),
+ style: Theme.of(context).textTheme.bodyMedium!.copyWith(
+ color: color,
+ ),
+ ),
+ ),
+ if (isActive)
+ Text(
+ context.l10n.active.toUpperCase(),
+ style: Theme.of(context).textTheme.bodyMedium!.copyWith(
+ fontWeight: FontWeight.w500,
+ fontSize: 11,
+ color: color,
+ ),
+ ),
+ ],
+ ),
+ ),
+ );
+ }
+
+ SvgGenImage get _icon => switch (stage) {
+ CampaignStage.draft => VoicesAssets.icons.clock,
+ CampaignStage.scheduled => VoicesAssets.icons.clock,
+ CampaignStage.live => VoicesAssets.icons.flag,
+ CampaignStage.completed => VoicesAssets.icons.calendar,
+ };
+
+ String _text(VoicesLocalizations l10n) => switch (stage) {
+ CampaignStage.draft => l10n.campaignPreviewEventBefore,
+ CampaignStage.scheduled => l10n.campaignPreviewEventBefore,
+ CampaignStage.live => l10n.campaignPreviewEventDuring,
+ CampaignStage.completed => l10n.campaignPreviewEventAfter,
+ };
+}
+
+class _EventTimelapseControls extends StatefulWidget {
+ final DateTime? nextStageTransitionAt;
+ final Duration stageTransitionDelay;
+ final VoidCallback? onPreviousStage;
+ final VoidCallback? onNextStage;
+ final ValueChanged onTransitionDelayChanged;
+
+ const _EventTimelapseControls({
+ required this.nextStageTransitionAt,
+ required this.stageTransitionDelay,
+ required this.onPreviousStage,
+ required this.onNextStage,
+ required this.onTransitionDelayChanged,
+ });
+
+ @override
+ State<_EventTimelapseControls> createState() =>
+ _EventTimelapseControlsState();
+}
+
+class _EventTimelapseControlsState extends State<_EventTimelapseControls> {
+ final _timerController = TextEditingController();
+ Timer? _refreshTimer;
+ bool _enabled = true;
+
+ @override
+ void initState() {
+ super.initState();
+
+ _refresh();
+ _restartRefreshTimer();
+ }
+
+ @override
+ void didUpdateWidget(_EventTimelapseControls oldWidget) {
+ super.didUpdateWidget(oldWidget);
+ _refresh();
+ _restartRefreshTimer();
+ }
+
+ @override
+ void dispose() {
+ _timerController.dispose();
+ _refreshTimer?.cancel();
+ super.dispose();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
+ child: Row(
+ children: [
+ Expanded(
+ child: VoicesTextButton(
+ leading: VoicesAssets.icons.rewind.buildIcon(),
+ onTap: widget.onPreviousStage,
+ child: Text(context.l10n.previous),
+ ),
+ ),
+ Container(
+ width: 60,
+ height: 56,
+ margin: const EdgeInsets.symmetric(horizontal: 16),
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.circular(8),
+ color: Theme.of(context).colors.elevationsOnSurfaceNeutralLv1Grey,
+ ),
+ alignment: Alignment.center,
+ child: TextField(
+ controller: _timerController,
+ onChanged: (_) => _onTransitionDelayChanged(),
+ enabled: _enabled,
+ decoration: null,
+ textAlign: TextAlign.center,
+ ),
+ ),
+ Expanded(
+ child: VoicesTextButton(
+ leading: VoicesAssets.icons.fastForward.buildIcon(),
+ onTap: widget.onNextStage,
+ child: Text(context.l10n.next),
+ ),
+ ),
+ ],
+ ),
+ );
+ }
+
+ void _restartRefreshTimer() {
+ _refreshTimer?.cancel();
+ _refreshTimer = Timer.periodic(
+ const Duration(seconds: 1),
+ (_) => _refresh(),
+ );
+ }
+
+ void _refresh() {
+ final now = DateTimeExt.now();
+ final nextStageTransitionAt = widget.nextStageTransitionAt;
+
+ if (nextStageTransitionAt != null && nextStageTransitionAt.isAfter(now)) {
+ final remainingDelay = nextStageTransitionAt.difference(now);
+ _updateTimerController(remainingDelay, enabled: false);
+ } else {
+ _updateTimerController(widget.stageTransitionDelay, enabled: true);
+ }
+ }
+
+ void _updateTimerController(Duration duration, {required bool enabled}) {
+ // only update if the duration is different,
+ // otherwise we might be overwriting local user edits
+ if (_stageTransitionDelay != duration) {
+ final seconds =
+ (duration.inMilliseconds / Duration.millisecondsPerSecond).ceil();
+ final text = '${seconds}s';
+ _timerController.value = TextEditingValue(
+ text: text,
+ selection: TextSelection.collapsed(offset: text.length),
+ );
+ }
+
+ if (enabled != _enabled) {
+ setState(() {
+ _enabled = enabled;
+ });
+ }
+ }
+
+ void _onTransitionDelayChanged() {
+ final duration = _stageTransitionDelay;
+ if (duration != null && duration != widget.stageTransitionDelay) {
+ widget.onTransitionDelayChanged(duration);
+ }
+ }
+
+ Duration? get _stageTransitionDelay {
+ final cleanedString =
+ _timerController.text.replaceAll('s', '').replaceAll(' ', '');
+ final seconds = int.tryParse(cleanedString);
+ return seconds != null ? Duration(seconds: seconds) : null;
+ }
+}
diff --git a/catalyst_voices/apps/voices/lib/pages/campaign/admin_tools/campaign_admin_tools_views.dart b/catalyst_voices/apps/voices/lib/pages/campaign/admin_tools/campaign_admin_tools_views.dart
new file mode 100644
index 00000000000..801d79e2fba
--- /dev/null
+++ b/catalyst_voices/apps/voices/lib/pages/campaign/admin_tools/campaign_admin_tools_views.dart
@@ -0,0 +1,60 @@
+import 'package:catalyst_voices/pages/campaign/admin_tools/campaign_admin_tools_dialog.dart';
+import 'package:catalyst_voices/widgets/buttons/voices_segmented_button.dart';
+import 'package:catalyst_voices_blocs/catalyst_voices_blocs.dart';
+import 'package:catalyst_voices_brands/catalyst_voices_brands.dart';
+import 'package:catalyst_voices_localization/catalyst_voices_localization.dart';
+import 'package:catalyst_voices_view_models/catalyst_voices_view_models.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+/// The "views" tab of the [CampaignAdminToolsDialog].
+class CampaignAdminToolsViewsTab extends StatelessWidget {
+ const CampaignAdminToolsViewsTab({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return Material(
+ color: Theme.of(context).colors.elevationsOnSurfaceNeutralLv1Grey,
+ child: Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.stretch,
+ children: [
+ Text(
+ context.l10n.userAuthenticationState,
+ style: Theme.of(context).textTheme.labelLarge,
+ ),
+ const SizedBox(height: 16),
+ const _SessionStatus(),
+ ],
+ ),
+ ),
+ );
+ }
+}
+
+class _SessionStatus extends StatelessWidget {
+ const _SessionStatus();
+
+ @override
+ Widget build(BuildContext context) {
+ return BlocSelector(
+ selector: (state) => state.sessionStatus,
+ builder: (context, sessionStatus) {
+ return VoicesSegmentedButton(
+ segments: [
+ for (final userState in SessionStatus.values)
+ ButtonSegment(
+ value: userState,
+ label: Text(userState.name(context.l10n)),
+ ),
+ ],
+ selected: {sessionStatus},
+ onChanged: (selected) {
+ context.read().updateSessionStatus(selected.first);
+ },
+ );
+ },
+ );
+ }
+}
diff --git a/catalyst_voices/apps/voices/lib/pages/campaign/details/campaign_details_dialog.dart b/catalyst_voices/apps/voices/lib/pages/campaign/details/campaign_details_dialog.dart
new file mode 100644
index 00000000000..684625386cc
--- /dev/null
+++ b/catalyst_voices/apps/voices/lib/pages/campaign/details/campaign_details_dialog.dart
@@ -0,0 +1,69 @@
+import 'dart:async';
+
+import 'package:catalyst_voices/dependency/dependencies.dart';
+import 'package:catalyst_voices/pages/campaign/details/widgets/campaign_header.dart';
+import 'package:catalyst_voices/pages/campaign/details/widgets/campaign_sections_list_view.dart';
+import 'package:catalyst_voices/widgets/widgets.dart';
+import 'package:catalyst_voices_blocs/catalyst_voices_blocs.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+class CampaignDetailsDialog extends StatefulWidget {
+ final String id;
+
+ const CampaignDetailsDialog._({
+ required this.id,
+ });
+
+ static Future show(
+ BuildContext context, {
+ required String id,
+ }) {
+ return VoicesDialog.show(
+ context: context,
+ routeSettings: RouteSettings(name: '/campaign/$id'),
+ builder: (context) => CampaignDetailsDialog._(id: id),
+ barrierDismissible: true,
+ );
+ }
+
+ @override
+ State createState() => _CampaignDetailsDialogState();
+}
+
+class _CampaignDetailsDialogState extends State {
+ late final CampaignDetailsBloc _bloc;
+
+ @override
+ void initState() {
+ super.initState();
+ _bloc = Dependencies.instance.get();
+ _bloc.add(LoadCampaignEvent(id: widget.id));
+ }
+
+ @override
+ void didUpdateWidget(covariant CampaignDetailsDialog oldWidget) {
+ super.didUpdateWidget(oldWidget);
+
+ if (widget.id != oldWidget.id) {
+ _bloc.add(LoadCampaignEvent(id: widget.id));
+ }
+ }
+
+ @override
+ void dispose() {
+ unawaited(_bloc.close());
+ super.dispose();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return BlocProvider.value(
+ value: _bloc,
+ child: const VoicesDetailsDialog(
+ header: CampaignHeader(),
+ body: CampaignSectionsListView(),
+ ),
+ );
+ }
+}
diff --git a/catalyst_voices/apps/voices/lib/pages/campaign/details/widgets/campaign_categories_tile.dart b/catalyst_voices/apps/voices/lib/pages/campaign/details/widgets/campaign_categories_tile.dart
new file mode 100644
index 00000000000..2d6fb5c77d6
--- /dev/null
+++ b/catalyst_voices/apps/voices/lib/pages/campaign/details/widgets/campaign_categories_tile.dart
@@ -0,0 +1,165 @@
+import 'package:catalyst_voices/widgets/menu/voices_modal_menu.dart';
+import 'package:catalyst_voices/widgets/tiles/voices_expansion_tile.dart';
+import 'package:catalyst_voices_brands/catalyst_voices_brands.dart';
+import 'package:catalyst_voices_localization/catalyst_voices_localization.dart';
+import 'package:catalyst_voices_view_models/catalyst_voices_view_models.dart';
+import 'package:collection/collection.dart';
+import 'package:flutter/foundation.dart';
+import 'package:flutter/material.dart';
+
+class CampaignCategoriesTile extends StatefulWidget {
+ final List sections;
+
+ const CampaignCategoriesTile({
+ super.key,
+ required this.sections,
+ });
+
+ @override
+ State createState() => _CampaignCategoriesTileState();
+}
+
+class _CampaignCategoriesTileState extends State {
+ String? _selectedSectionId;
+
+ @override
+ void initState() {
+ super.initState();
+
+ _selectedSectionId = widget.sections.firstOrNull?.id;
+ }
+
+ @override
+ void didUpdateWidget(covariant CampaignCategoriesTile oldWidget) {
+ super.didUpdateWidget(oldWidget);
+
+ if (!listEquals(widget.sections, oldWidget.sections)) {
+ if (!widget.sections.any((element) => element.id == _selectedSectionId)) {
+ _selectedSectionId = widget.sections.firstOrNull?.id;
+ }
+ }
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ final selectedSection = widget.sections
+ .singleWhereOrNull((element) => element.id == _selectedSectionId);
+
+ return VoicesExpansionTile(
+ initiallyExpanded: true,
+ title: Text(context.l10n.campaignCategories),
+ children: [
+ Row(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ _Menu(
+ selectedId: _selectedSectionId,
+ menuItems: widget.sections,
+ onTap: _updateSelection,
+ ),
+ const SizedBox(width: 32),
+ Expanded(
+ child: selectedSection != null
+ ? _Details(section: selectedSection)
+ : const SizedBox(),
+ ),
+ ],
+ ),
+ ],
+ );
+ }
+
+ void _updateSelection(String id) {
+ setState(() {
+ _selectedSectionId = id;
+ });
+ }
+}
+
+class _Menu extends StatelessWidget {
+ final String? selectedId;
+ final List