diff --git a/.specify/feature.json b/.specify/feature.json index bd027e8..5fa703e 100644 --- a/.specify/feature.json +++ b/.specify/feature.json @@ -1,3 +1,3 @@ { - "feature_directory": "specs/016-openspec-migration" + "feature_directory": "specs/015-tsc-charter" } diff --git a/CHARTER.md b/CHARTER.md new file mode 100644 index 0000000..972d758 --- /dev/null +++ b/CHARTER.md @@ -0,0 +1,130 @@ +# darnit Technical Charter + +This Technical Charter (the "Charter") sets forth the responsibilities and procedures for technical contribution to, and oversight of, the darnit Project (the "Project"). + +## 1. Mission and Scope of the Project + +The mission of the darnit Project is to provide an extensible, AI-assisted compliance auditing framework that separates a vendor-neutral core from pluggable compliance implementations, so that open source projects can be audited against multiple security and governance baselines (e.g., the OpenSSF Baseline) without re-implementing the auditing engine. + +The scope of the Project includes the framework, its first-party compliance implementations maintained in the same repository, and the tooling required to author, validate, and ship those implementations. + +## 2. Technical Steering Committee + +### 2.1 Composition + +The Project is governed by a Technical Steering Committee (the "TSC"). The TSC operates as a single-tier body: there is one TSC for the entire Project, regardless of the number of packages or implementations the Project ships. + +The current voting members of the TSC are listed in [TECHNICAL-STEERING-COMMITTEE.md](./TECHNICAL-STEERING-COMMITTEE.md), with affiliation and industry-or-academia category disclosed for each member. + +The TSC has no fixed maximum size. Membership is not time-bounded -- members serve until resignation or removal under Section 2.5. + +### 2.2 Responsibilities + +The TSC is responsible for oversight of the Project, including: + +- Setting the Project's overall technical direction; +- Approving Project releases and security policy; +- Organizing, creating, and removing sub-projects or working groups; +- Appointing representatives to other communities and foundations on the Project's behalf; +- Establishing community norms, contribution workflows, and review processes; +- Voting on cross-Project technical matters; and +- Amending this Charter under Section 8. + +The TSC MAY delegate operational responsibilities -- such as day-to-day Pull Request review and release execution -- to maintainers under separate community documentation. Such delegation does not transfer the TSC's authority; the TSC remains the source of policy. + +### 2.3 Chair + +The TSC MAY elect a Chair from among its members. The Chair, if elected, presides over TSC discussions and serves as the Project's primary point of contact for foundation liaisons. The Chair serves until resignation or replacement by a subsequent TSC vote. The Project does not require a Chair to function; in the absence of a Chair, foundation liaison MAY be designated ad hoc by simple majority of the TSC for the matter at hand. + +### 2.4 Adding a Member + +A candidate for TSC membership is nominated by an existing TSC member. The nomination is recorded as a Pull Request that adds a row to [TECHNICAL-STEERING-COMMITTEE.md](./TECHNICAL-STEERING-COMMITTEE.md) populated with the candidate's name, affiliation, category, and GitHub handle. + +Existing TSC members vote on the nomination by approving or declining the Pull Request. The candidate is added to the TSC when a majority of the entire current TSC has approved the Pull Request, in accordance with Section 3 (TSC Voting). The merge commit is the canonical record of the decision. + +### 2.5 Removing a Member + +A TSC member MAY resign at any time by opening a Pull Request that removes their row from [TECHNICAL-STEERING-COMMITTEE.md](./TECHNICAL-STEERING-COMMITTEE.md). A resignation Pull Request does not require a vote; acknowledgment by another TSC member who merges the Pull Request suffices. + +A TSC member MAY be removed for cause -- including, but not limited to, inactivity or a serious violation of the Project's Code of Conduct -- by a vote of the *other* current TSC members. The member under review MUST NOT vote on their own removal. Removal for cause requires the approval of a majority of the other current TSC members, at the same level as ordinary TSC decisions. + +For the purposes of this Section, "inactivity" is not defined by a fixed numeric threshold (such as a specific number of months without contribution). Inactivity is a discretionary judgment by the remaining TSC members, initiated by a public GitHub Issue or Pull Request describing the basis for the proposed removal and resolved by the removal-for-cause threshold above. + +## 3. TSC Voting + +The TSC's goal is to operate as a consensus-based community. When a decision cannot be reached by consensus, the TSC MAY decide the matter by a vote conducted in accordance with this Section. + +### 3.1 General Voting Rules + +- Each TSC member has one vote. +- Quorum for a vote is fifty percent (50%) of the current voting members of the TSC. +- For a meeting or synchronous vote in which a quorum is present, a decision is approved by a simple majority of the members voting in favor versus against; abstentions do not count toward the total. Ties fail. +- For decisions conducted electronically (e.g., on a Pull Request or GitHub Issue rather than in a meeting), a decision is approved when a majority of the entire TSC has voted in favor. +- Amendments to this Charter (Section 8) and exceptions to the Project's stated license policy (Section 7) require the approval of at least two-thirds (2/3) of the entire TSC, not merely of those voting. + +### 3.2 Recording Votes + +Votes on decisions that modify a tracked file -- the roster, this Charter, or any other policy file in the repository -- are recorded by GitHub Pull Request approvals on the affected file. The Pull Request review state and the resulting merge commit constitute the canonical vote record. + +Votes on decisions that do not modify a file (for example, approving a representative to an external community, or endorsing an external statement on the Project's behalf) are recorded in a GitHub Issue or Discussion thread. Each TSC member casts a vote as an explicit comment of `+1`, `-1`, or `+0` on a single comment line, so that the tally is unambiguous to a casual reader and parseable by tooling. Subsequent artifacts that depend on the decision MUST link to the recording Issue or Discussion. + +### 3.3 Deadlocks + +If the TSC is unable to reach quorum, or to resolve a deadlock through ordinary voting under Section 3.1, the matter MAY be escalated to the LF Projects Series Manager once the Project is hosted under The Linux Foundation. Until such time as the Project is formally hosted, deadlocks are resolved by good-faith re-discussion among the TSC members. + +## 4. Compliance with Policies + +### 4.1 Code of Conduct + +The TSC and all Project contributors are subject to the Project's Code of Conduct, when adopted. Until the Project adopts a Code of Conduct of its own, the [LF Projects Code of Conduct](https://lfprojects.org/policies/code-of-conduct/) applies by default. + +### 4.2 Trademark and Antitrust + +The Project's name and any associated trademarks are the property of their respective holders. The TSC operates in compliance with applicable antitrust laws and avoids any discussion or action that would constitute unlawful coordination among competing organizations. + +### 4.3 Developer Certificate of Origin + +All contributions to the Project, including contributions to this Charter, MUST be signed off under the [Developer Certificate of Origin (DCO) version 1.1](https://developercertificate.org/). + +## 5. Community Assets + +The Project maintains the following community assets: + +- **Source repository**: +- **Issues**: +- **Discussions**: +- **Security reports**: see [SECURITY.md](./SECURITY.md) + +Additional assets -- for example, mailing lists, chat channels, or meeting venues -- MAY be added by TSC decision and announced through the Project's existing channels. + +## 6. General Rules and Operations + +The TSC will operate in a transparent, open, collaborative, and ethical manner at all times. The TSC will not seek to exclude any participant on any criteria other than those that are reasonable and applied on a non-discriminatory basis. + +All TSC meetings, when held, are open to the public. Decisions reached outside of meetings (for example, on Pull Requests or in Issues per Section 3.2) are public by virtue of the venue. + +TSC members are expected to disclose any conflicts of interest material to a decision before the TSC and to recuse themselves from decisions where their impartiality would be reasonably questioned. + +## 7. Intellectual Property Policy + +The Project ships the following classes of work under the following licenses: + +- **Source code** is licensed under the Apache License, version 2.0. +- **Documentation**, including this Charter, is licensed under the Creative Commons Attribution 4.0 International License (CC-BY-4.0). +- **Data** distributed by the Project is licensed under the Community Data License Agreement -- Permissive, version 2.0 (CDLA-Permissive-2.0). + +Contributions to the Project MUST be made under terms compatible with these licenses. Exceptions to the license stack require a vote of the TSC under Section 3.1 with the two-thirds threshold. + +## 8. Amendments + +This Charter MAY be amended by a Pull Request modifying this document, approved by at least two-thirds (2/3) of the entire TSC in accordance with Section 3. + +A proposed amendment SHOULD be announced through the Project's existing communication channels and allow a reasonable comment window before merge, so that the community has the opportunity to weigh in. + +--- + +**Adopted**: 2026-06-17 + +**Provenance**: Adapted from the LF Projects Technical Charter, also used by the [GUAC](https://github.com/guacsec/governance) and [gittuf](https://github.com/gittuf/community) projects. + +**License**: This document is licensed under the Creative Commons Attribution 4.0 International License (CC-BY-4.0). diff --git a/CLAUDE.md b/CLAUDE.md index 68e6bf8..0e8fd9a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -366,5 +366,5 @@ else: For additional context about technologies to be used, project structure, shell commands, and other important information, read the current plan: -[`specs/016-openspec-migration/plan.md`](specs/016-openspec-migration/plan.md) +[`specs/015-tsc-charter/plan.md`](specs/015-tsc-charter/plan.md) diff --git a/GOVERNANCE.md b/GOVERNANCE.md index 3eaf432..c00524b 100644 --- a/GOVERNANCE.md +++ b/GOVERNANCE.md @@ -1,6 +1,8 @@ # Governance -This document describes the governance model for the darnit project. +The darnit Project is governed by a Technical Steering Committee (TSC). The binding rules for membership, voting, and amendments live in the Project's [Charter](./CHARTER.md); the current voting members of the TSC are listed in [TECHNICAL-STEERING-COMMITTEE.md](./TECHNICAL-STEERING-COMMITTEE.md). + +This document describes the operational layer below the Charter: how the Project is organized, what roles contributors fill, and how routine activities (PR review, releases) are run on a day-to-day basis. The Charter is the authority on governance decisions; this document is operational guidance and may be revised by maintainer consensus without a TSC vote. ## Project Structure @@ -15,6 +17,8 @@ Future plugins can be developed as external packages following the plugin archit ## Roles and Responsibilities +The TSC sets policy. The roles below operate under that policy and are responsible for day-to-day execution. TSC members are typically also maintainers, but the two roles are distinct: TSC authority comes from the [Charter](./CHARTER.md); maintainer authority comes from commit access granted by the TSC. + ### Maintainers Maintainers have write access to the repository and are responsible for: @@ -22,7 +26,7 @@ Maintainers have write access to the repository and are responsible for: - Reviewing and merging pull requests - Managing releases and versioning - Responding to security vulnerabilities -- Setting project direction and priorities +- Day-to-day technical direction within policy set by the TSC - Enforcing the Code of Conduct ### Contributors @@ -42,21 +46,26 @@ A specialized contributor role for those who: - Implement sieve verification adapters - Write remediation functions -## Decision Making +## Day-to-Day PR Process + +The following thresholds apply to routine PR activity. Changes to *governance itself* -- this document, the [Charter](./CHARTER.md), or the [TSC roster](./TECHNICAL-STEERING-COMMITTEE.md) -- follow the TSC voting rules in the Charter instead. ### Minor Changes + - Standard PR review and approval process - One maintainer approval required ### Major Changes + - Open a GitHub Issue for discussion first - Allow community input before implementation - Document rationale in the PR ### Breaking Changes + - Require RFC (Request for Comments) process - Minimum 7-day comment period -- Requires consensus from maintainers +- Approval by maintainer consensus ## Release Process @@ -66,13 +75,14 @@ A specialized contributor role for those who: 4. Automated PyPI publish via CI (when enabled) Releases follow [Semantic Versioning](https://semver.org/): + - MAJOR: Breaking changes - MINOR: New features (backwards compatible) - PATCH: Bug fixes (backwards compatible) ## Code of Conduct -All participants are expected to uphold a welcoming, harassment-free environment. Be respectful, constructive, and inclusive in all interactions. +All participants are expected to uphold a welcoming, harassment-free environment. Be respectful, constructive, and inclusive in all interactions. The Project intends to adopt a project-specific Code of Conduct; until then, the LF Projects Code of Conduct applies per the [Charter](./CHARTER.md), Section 4.1. ## Contact diff --git a/README.md b/README.md index 07d6cfd..6766771 100644 --- a/README.md +++ b/README.md @@ -436,6 +436,10 @@ To report security vulnerabilities, see [SECURITY.md](SECURITY.md). For contributor setup and development workflow, see the [Getting Started Guide](GETTING_STARTED.md). +## Governance + +The darnit Project is governed by a Technical Steering Committee (TSC). See the [Charter](CHARTER.md) for the binding governance rules, the [TSC roster](TECHNICAL-STEERING-COMMITTEE.md) for current voting members, and [GOVERNANCE.md](GOVERNANCE.md) for operational guidance (roles, release process, contact). + ## License Apache-2.0 diff --git a/TECHNICAL-STEERING-COMMITTEE.md b/TECHNICAL-STEERING-COMMITTEE.md new file mode 100644 index 0000000..93c5f82 --- /dev/null +++ b/TECHNICAL-STEERING-COMMITTEE.md @@ -0,0 +1,14 @@ +# Technical Steering Committee + + + +The current voting members of the darnit Technical Steering Committee are: + +| Name | Affiliation | Category | GitHub | Role | +|------|-------------|----------|--------|------| +| Michael Lieberman | Kusari | industry | @mlieberman85 | member | +| Justin Cappos | New York University | academia | @JustinCappos | member | +| Stephen Augustus | Bloomberg | industry | @justaugustus | member | +| Adolfo Garcia Veytia | Carabiner | industry | @puerco | member | + +For the rules that govern membership, voting, and amendments, see [CHARTER.md](./CHARTER.md). diff --git a/specs/015-tsc-charter/checklists/requirements.md b/specs/015-tsc-charter/checklists/requirements.md new file mode 100644 index 0000000..3d8772d --- /dev/null +++ b/specs/015-tsc-charter/checklists/requirements.md @@ -0,0 +1,47 @@ +# Specification Quality Checklist: Technical Steering Committee Charter + +**Purpose**: Validate specification completeness and quality before proceeding to planning +**Created**: 2026-06-17 +**Feature**: [spec.md](../spec.md) + +## Content Quality + +- [x] No implementation details (languages, frameworks, APIs) +- [x] Focused on user value and business needs +- [x] Written for non-technical stakeholders +- [x] All mandatory sections completed + +## Requirement Completeness + +- [x] No [NEEDS CLARIFICATION] markers remain +- [x] Requirements are testable and unambiguous +- [x] Success criteria are measurable +- [x] Success criteria are technology-agnostic (no implementation details) +- [x] All acceptance scenarios are defined +- [x] Edge cases are identified +- [x] Scope is clearly bounded +- [x] Dependencies and assumptions identified + +## Feature Readiness + +- [x] All functional requirements have clear acceptance criteria +- [x] User scenarios cover primary flows +- [x] Feature meets measurable outcomes defined in Success Criteria +- [x] No implementation details leak into specification + +## Notes + +- Spec mirrors the LF Projects Technical Charter pattern used by both reference + projects (GUAC's two-tier structure was deliberately rejected in favor of + gittuf's single-tier; rationale captured in Assumptions). +- The two-member founding roster creates a known transitional posture where + one member can carry a non-amendment vote. This is documented as an explicit + assumption rather than treated as a defect; recruiting a third member is + noted as a near-term action. +- Three reasonable areas of judgment (charter location in-repo vs separate + governance repo, diversity-by-transparency vs hard employer quota, no fixed + terms / no required chair) were resolved by mirroring gittuf precedent and + documented in Assumptions, not raised as [NEEDS CLARIFICATION] questions, + consistent with the user's "real quick" framing. +- No items remain incomplete; spec is ready for `/speckit-plan`. `/speckit-clarify` + is unnecessary unless the user wants to revisit any of the assumptions above. diff --git a/specs/015-tsc-charter/data-model.md b/specs/015-tsc-charter/data-model.md new file mode 100644 index 0000000..ecb244a --- /dev/null +++ b/specs/015-tsc-charter/data-model.md @@ -0,0 +1,122 @@ +# Phase 1 Data Model: TSC Charter Artifacts + +**Feature**: 015-tsc-charter | **Date**: 2026-06-17 + +This feature ships no runtime data -- the "data model" here describes the Markdown document shapes the charter and roster files MUST conform to. Each shape is testable against the spec's success criteria. + +## Entity 1 -- Charter document (`CHARTER.md`) + +The charter follows the LF Projects Technical Charter template structure, mirroring GUAC and gittuf. + +### Required sections (in order) + +| # | Section heading | Required content | +|---|---|---| +| 1 | Mission and Scope of the Project | One paragraph stating darnit's mission (AI-assisted compliance auditing with a plugin architecture) and the scope the TSC stewards. References the spec's FR-003 enumeration of authority. | +| 2 | Technical Steering Committee | Composition rules (single-tier, members initially = founding committers per D2/D3). Pointer to `TECHNICAL-STEERING-COMMITTEE.md` for the live roster. Membership change process (FR-005), removal process (FR-006), chair (D8). | +| 3 | TSC Voting | Decision-making rules: consensus-first; voting fallback per FR-004 (one vote per member, 50% quorum, simple majority of attendees, 2/3 of entire TSC for amendments and license exceptions). Vote recording mechanism per FR-013. | +| 4 | Compliance with Policies | CoC pointer (D10), DCO requirement (FR-008), trademark notes if applicable, antitrust compliance language from the LF template. | +| 5 | Community Assets | Repositories, mailing lists, communication channels owned by the project. | +| 6 | General Rules and Operations | Transparency obligations, conflict of interest, non-discrimination language from the LF template. | +| 7 | Intellectual Property Policy | License stack per FR-008 (Apache-2.0 code, CC-BY-4.0 docs, CDLA-Permissive-2.0 data). | +| 8 | Amendments | Amendment process and threshold (2/3 of entire TSC, per FR-010 referencing FR-004). | + +### Required metadata (in document) + +- **License notice**: "This document is licensed under CC-BY-4.0." (FR-009) +- **Adopted date**: ISO-8601 date when the charter is first merged (analogous to gittuf's "Adopted: November 2nd, 2023"). +- **Provenance line**: "Adapted from the LF Projects Technical Charter, also used by GUAC and gittuf." + +### Validation rules + +| Rule | Check | +|---|---| +| All eight sections present in order | Heading count + order matches the table above (SC-002). | +| No `[NEEDS CLARIFICATION]` markers | `grep -n "NEEDS CLARIFICATION" CHARTER.md` returns nothing. | +| Voting thresholds consistent | Every numeric threshold in narrative text matches the Voting section (SC-005). | +| License notice present | Document contains "CC-BY-4.0" verbatim once. | + +## Entity 2 -- Roster (`TECHNICAL-STEERING-COMMITTEE.md`) + +The roster is a parseable list. Each member is exactly one row in a Markdown table; adding or removing a member is a one-line edit (FR-011). + +### Row schema + +| Column | Type | Required | Constraints | +|---|---|---|---| +| `Name` | string | yes | Full personal name. | +| `Affiliation` | string | yes | Organization (employer, university, "Independent"). | +| `Category` | enum | yes | One of: `industry`, `academia`, `independent`. | +| `GitHub` | string | yes | GitHub handle prefixed with `@`. Must resolve to an existing GitHub user at insertion time. | +| `Role` | enum | optional | One of: `member`, `chair`. Default: `member`. Only one row may carry `chair` at a time. | + +### Required document structure + +```markdown +# Technical Steering Committee + + + +The current voting members of the darnit Technical Steering Committee are: + +| Name | Affiliation | Category | GitHub | Role | +|------|-------------|----------|--------|------| +| Michael Lieberman | Kusari | industry | @mlieberman85 | member | +| Justin Cappos | New York University | academia | @JustinCappos | member | +| Stephen Augustus | Bloomberg | industry | @justaugustus | member | +| Adolfo Garcia Veytia | Carabiner | industry | @puerco | member | + +For the rules that govern membership, voting, and amendments, see +[CHARTER.md](./CHARTER.md). +``` + +### Validation rules + +| Rule | Check | +|---|---| +| All four required columns populated for every row | No empty cells in `Name`, `Affiliation`, `Category`, `GitHub` (SC-003). | +| `Category` is one of the enum values | Each row's `Category` matches `industry\|academia\|independent`. | +| `GitHub` handle prefixed with `@` | Regex `^@[A-Za-z0-9-]+$` per row. | +| At most one chair | `grep -c "| chair " TECHNICAL-STEERING-COMMITTEE.md` <= 1. | +| Initial roster matches user input | Four founding rows in joining order: Michael Lieberman / Kusari / industry / @mlieberman85; Justin Cappos / New York University / academia / @JustinCappos; Stephen Augustus / Bloomberg / industry / @justaugustus; Adolfo Garcia Veytia / Carabiner / industry / @puerco. | + +### State transitions + +```text + propose majority of TSC edit roster row +[Candidate] ------------> [Pending] ------------------------> [Accepted] -----------------> [Member] + (PR approvals or | + issue/discussion | resign / removed-for-cause + vote per FR-013) | (majority of other TSC members) + v + [Departed] +``` + +State transitions are recorded by edits to the roster file plus the corresponding PR/issue thread. No separate state-tracking artifact is required. + +## Entity 3 -- Governance index (`GOVERNANCE.md`) + +A short discoverability index pointing to the two documents above. Not a substitute for either. + +### Required content + +- Single H1: "darnit Project Governance". +- One paragraph stating that darnit is governed by a TSC. +- Two links: one to `CHARTER.md`, one to `TECHNICAL-STEERING-COMMITTEE.md`, each with a one-line description. +- Optional pointer to the project Code of Conduct when one is adopted. + +### Validation rules + +| Rule | Check | +|---|---| +| Both target documents exist | The two links resolve to files in the same directory. | +| File is short | <=30 lines of Markdown (it is an index, not content). | + +## Cross-document invariants + +| Invariant | Documents involved | Check | +|---|---|---| +| Roster cited in charter matches actual roster file | `CHARTER.md` <-> `TECHNICAL-STEERING-COMMITTEE.md` | The charter's Section 2 names the roster file by path; it does not duplicate member rows. | +| License posture consistent | All three new files | Each contains "CC-BY-4.0" notice in a comment, footer, or stated license line. | +| Vote-recording mechanism cited once | `CHARTER.md` only | FR-013's mechanism is stated in the Voting section of the charter; not duplicated elsewhere. | +| No member's name appears outside the roster | `CHARTER.md` <-> `TECHNICAL-STEERING-COMMITTEE.md` | A search for a member's GitHub handle in `CHARTER.md` returns zero matches (the charter refers to "the TSC", not to individuals -- so a future member change requires editing one file, satisfying FR-011 and SC-004). | diff --git a/specs/015-tsc-charter/plan.md b/specs/015-tsc-charter/plan.md new file mode 100644 index 0000000..276e4a8 --- /dev/null +++ b/specs/015-tsc-charter/plan.md @@ -0,0 +1,95 @@ +# Implementation Plan: Technical Steering Committee Charter + +**Branch**: `015-tsc-charter` | **Date**: 2026-06-17 | **Spec**: [spec.md](./spec.md) + +**Input**: Feature specification from `/specs/015-tsc-charter/spec.md` + +## Summary + +Author a Technical Steering Committee (TSC) charter and roster for the darnit project, modeled on gittuf's single-tier governance pattern (and adopting the LF Projects Technical Charter section structure shared by both gittuf and GUAC). The deliverable is **documentation only** -- Markdown files at the repository root. No runtime code is added. + +The work product is three files: `CHARTER.md` (the governance document), `TECHNICAL-STEERING-COMMITTEE.md` (the machine-friendly roster), and a small `GOVERNANCE.md` index linking both from a single discoverable entry point. The initial roster lists Michael Lieberman (Kusari, industry, @mlieberman85) and Justin Cappos (New York University, academia, @JustinCappos). + +Vote recording follows gittuf's pattern (clarified in spec session 2026-06-17): GitHub PR approvals on the affected file are the canonical record for file-bound decisions; GitHub Issue/Discussion threads with explicit `+1`/`-1`/`+0` comments cover decisions without a file artifact. Removal-for-cause uses majority of *other* TSC members; inactivity is discretionary (no fixed numeric threshold). + +## Technical Context + +**Language/Version**: Markdown (CommonMark, GitHub-flavored). No source code. + +**Primary Dependencies**: None at build/runtime. Authoring relies only on text editors and the GitHub web UI for PR review. + +**Storage**: Git repository (`kusari-oss/darnit` main repo). No database, no external store. Roster history is recoverable from `git log`. + +**Testing**: Manual review against the spec's checklist (`specs/015-tsc-charter/checklists/requirements.md`). No automated test framework is required for v1, though a future task may add a CI lint that validates the roster file's parseable structure. + +**Target Platform**: GitHub-hosted Markdown rendering (web + raw). Files are also expected to render acceptably in any LF Projects / OpenSSF reviewer's Markdown viewer. + +**Project Type**: Project governance documentation (not a code feature). Single deliverable bundle of Markdown files. + +**Performance Goals**: N/A. The artifact is a static text document. + +**Constraints**: +- Charter document content licensed under CC-BY-4.0 (per FR-009). +- Charter MUST be discoverable from the repository root (per FR-012) -- a top-level `GOVERNANCE.md` index is the chosen entry point. +- Roster format MUST be parseable as a single edit per member change (per FR-011). +- No bespoke two-member quorum rule (per spec Assumptions); the transitional two-member posture was accepted at initial draft time and rendered moot on 2026-06-18 when the founding TSC was expanded to four members before adoption. + +**Scale/Scope**: +- Four founding members (Lieberman, Cappos, Augustus, Garcia Veytia) as of 2026-06-18. Initial draft posited two founding members; the founding roster was expanded before adoption. +- One charter document, one roster file, one governance index. +- ~600-1200 lines of Markdown total expected. + +## Constitution Check + +*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.* + +The darnit constitution (v1.1.0, 2026-03-08) defines five principles, all of which govern runtime behavior of the audit framework code. This feature ships **no code** -- only Markdown governance documents. Each principle is therefore inapplicable rather than violated: + +| Principle | Applicability | Note | +|---|---|---| +| I. Plugin Separation | N/A | No Python packages added; no imports. | +| II. Conservative-by-Default | N/A | No control checks; no PASS/FAIL/WARN computation. | +| III. TOML-First Architecture | N/A | No controls defined; no TOML touched. | +| IV. Never Guess User Values | N/A -- and aligned in spirit | The charter codifies *human* decision authority for governance decisions, which is consistent with the principle's stance against silent automation. The founding-member identities and affiliations were supplied explicitly by the user, not auto-detected. | +| V. Sieve Pipeline Integrity | N/A | No sieve handlers added; pipeline untouched. | + +The Development Workflow section of the constitution (lint / tests / spec sync / generated docs / upstream rebase) still applies operationally: the PR that introduces these files MUST pass `ruff check` (no-op on Markdown), `pytest` (unchanged), and `validate_sync.py` (unchanged -- this feature does not modify the framework-design spec). + +**Gate result**: PASS. No constitutional violations; no complexity-tracking entries required. + +## Project Structure + +### Documentation (this feature) + +```text +specs/015-tsc-charter/ ++-- plan.md # This file (/speckit-plan command output) ++-- spec.md # Feature specification (/speckit-specify output) ++-- research.md # Phase 0 output (GUAC + gittuf pattern analysis) ++-- data-model.md # Phase 1 output (roster schema + charter outline) ++-- quickstart.md # Phase 1 output (governance operating instructions) ++-- checklists/ +| +-- requirements.md # Spec quality checklist (from /speckit-specify) ++-- tasks.md # Phase 2 output (/speckit-tasks -- NOT created here) +``` + +No `contracts/` directory is created: this feature exposes no APIs, command schemas, network endpoints, or parser grammars. The roster's row schema (documented in `data-model.md`) is the closest equivalent to an external contract and is captured there. + +### Repository Root (deliverable artifacts) + +The plan delivers exactly three new top-level files in the main repository, and one CLAUDE.md pointer update: + +```text +/ (repository root) ++-- GOVERNANCE.md # NEW -- discoverability index (FR-012) ++-- CHARTER.md # NEW -- the LF-template-shaped charter (FR-001, FR-003..FR-010, FR-013) ++-- TECHNICAL-STEERING-COMMITTEE.md # NEW -- the parseable roster (FR-002, FR-011) +``` + +Optionally, a README.md edit may add a one-line link to `GOVERNANCE.md` to satisfy "linked from the README" alternative in FR-012; this is decided in the `/speckit-tasks` phase. + +**Structure Decision**: Three top-level Markdown files plus an index. The split (`CHARTER.md` <-> `TECHNICAL-STEERING-COMMITTEE.md`) mirrors gittuf's structure exactly so that future readers familiar with gittuf can navigate without retraining. `GOVERNANCE.md` is a lightweight index because the LF template document itself (`CHARTER.md`) is long and a one-screen entry point improves discoverability (SC-001 -- "under 2 minutes" to find current TSC + change rule). + +## Complexity Tracking + +No constitution violations. Table omitted. diff --git a/specs/015-tsc-charter/quickstart.md b/specs/015-tsc-charter/quickstart.md new file mode 100644 index 0000000..bc1bb85 --- /dev/null +++ b/specs/015-tsc-charter/quickstart.md @@ -0,0 +1,53 @@ +# Quickstart: Operating Under the TSC Charter + +**Feature**: 015-tsc-charter | **Date**: 2026-06-17 + +A practical guide for the four most common governance actions once the charter and roster files are in place. Each action references the relevant FR(s) from `spec.md` and lines up directly with the validation rules in `data-model.md`. + +## Adding a TSC member + +1. **Open a PR** that adds one row to `TECHNICAL-STEERING-COMMITTEE.md` with all four required columns (`Name`, `Affiliation`, `Category`, `GitHub`) populated. +2. **Tag the PR** with `governance/tsc-membership` (or whatever label convention the repo adopts) and link to the PR in a GitHub Issue titled `TSC: add ` for community visibility. +3. **Solicit votes**: existing TSC members approve or comment on the PR. Per FR-013, PR review approvals are the canonical vote record. +4. **Merge condition**: majority of existing TSC members approve (FR-004 + FR-005). +5. **Record**: the merge commit is the audit trail. No separate minutes entry required. + +## Removing a TSC member (voluntary resignation) + +1. The departing member opens a PR removing their row from `TECHNICAL-STEERING-COMMITTEE.md`. +2. A non-departing TSC member approves the PR (acknowledgment, not a vote -- voluntary resignations need no vote). +3. The departing member or any TSC member merges. + +## Removing a TSC member (for cause) + +1. Any TSC member opens a public GitHub Issue titled `TSC: remove for cause` describing the reason (inactivity, conduct, etc.). Per D7, "inactivity" is not a fixed numeric threshold -- it's a discretionary judgment captured in the issue body. +2. The same member (or another) opens a PR removing the affected member's row from `TECHNICAL-STEERING-COMMITTEE.md`, linking the issue. +3. **Approval threshold**: majority of the *other* current TSC members (the member under review does not vote on their own removal), per FR-006. +4. Once the threshold is met, merge. The merge commit + the linked issue form the audit trail. + +**Note**: an earlier draft of this guide warned that with only two TSC members, "majority of the other members" collapses to a majority of one. That concentration risk was specific to a two-member regime and became moot when the founding TSC was expanded to four members before adoption (see `spec.md` Clarifications, Session 2026-06-18). With four members, "majority of the other members" means at least two of three. + +## Amending the charter + +1. Open a PR modifying `CHARTER.md` (or `TECHNICAL-STEERING-COMMITTEE.md` for roster format changes, though those typically don't require an amendment vote). +2. Open a companion GitHub Issue titled `Charter amendment: ` with the rationale and a link to the PR. Announce the proposal on community channels (mailing list, Slack) per the LF template's transparency obligation. +3. **Approval threshold**: two-thirds of the *entire* TSC (not just attendees), per FR-004 and FR-010. Recorded as PR approvals on `CHARTER.md`. +4. After the threshold is met, allow a brief comment window (>= a few days is typical; the LF template does not mandate an exact length) before merging, so the community has time to weigh in. +5. Merge. + +## Recording a TSC decision that doesn't modify a file + +For decisions like "endorse external statement X" or "appoint as representative to ": + +1. Open a GitHub Issue titled `TSC decision: ` with the proposal in the body. +2. TSC members comment with `+1`, `-1`, or `+0` on a single comment line each (so the votes are unambiguous to a casual reader and parseable by tooling). Per FR-013, this is the canonical record. +3. Apply the relevant voting threshold (ordinary majority unless the decision is an amendment or license exception). +4. Once the threshold is met, the issue is closed with a closing comment naming the outcome. The closed issue is the audit trail. + +## Sanity check before submitting any governance PR + +- [ ] Only one file is being modified (roster change) OR the change is clearly a charter-amendment-class change. +- [ ] The PR description names the relevant charter section/FR governing this change. +- [ ] If the change affects the roster, every row still has all four required columns populated. +- [ ] If the change affects voting thresholds in the charter narrative, the Voting section was updated to match (SC-005). +- [ ] The relevant GitHub Issue (for non-file decisions) is linked in the PR description. diff --git a/specs/015-tsc-charter/research.md b/specs/015-tsc-charter/research.md new file mode 100644 index 0000000..808e841 --- /dev/null +++ b/specs/015-tsc-charter/research.md @@ -0,0 +1,104 @@ +# Phase 0 Research: TSC Charter Patterns + +**Feature**: 015-tsc-charter | **Date**: 2026-06-17 + +This phase consolidates the GUAC and gittuf TSC patterns the spec is modeled on, captures the contested design choices, and records the decision + rationale + rejected alternatives for each one. Per the spec's clarifications session (2026-06-17), all open ambiguities are resolved. + +## Source Material + +### GUAC + +- **Authoritative location**: `guacsec/governance` repo. Documents: `CHARTER.MD` (LF Projects Technical Charter), `GOVERNANCE.md`, `STEERING_COMMITTEE`, `MAINTAINERS.`, `CODE_OF_CONDUCT.md`. License: CC BY 4.0. +- **Structure**: Two-tier. A GUAC Steering Committee sits above multiple Core Projects (GUAC, Trustify) which each run their own contributor ladder. +- **TSC composition**: 3 general seats + 1 per core project (latter must be a maintainer on that core project). Affiliation diversity hard rule: at least 2 different employers. Minimum 3 active members. No fixed terms; inactivity >3 months = removal. +- **Add/remove**: Public proposal as governance-repo issue, announced on all community channels, 2-week window, simple majority of SC. +- **Voting**: Consensus-first. Voting fallback: one vote per member, simple majority of attendees with 50% quorum. Charter amendments and license exceptions require 2/3 of the entire TSC. +- **Chair**: Optional. Serves until resignation or replacement; no fixed term. +- **Meetings**: Public; minutes in `meetings/`. + +### gittuf + +- **Authoritative location**: `gittuf/community` repo. Documents: `CHARTER.md` (LF Projects Technical Charter), `TECHNICAL-STEERING-COMMITTEE.md` (roster with affiliation + industry/academia tag), `CONTRIBUTOR_LADDER.md`, `CODE-OF-CONDUCT.md`. Main code repo carries `MAINTAINERS.txt`. +- **Structure**: Single-tier. One project, one TSC. +- **TSC composition**: Initially = the project's Committers. Roster currently 5 people, each labelled with affiliation + industry/academia tag. No hard quota. No fixed size, no term limits. +- **Add/remove**: "Contributor may become a Committer by a majority approval of the existing Committers." Removal by majority approval of the *other* existing Committers. Promotion criteria (substantial PRs / reviews) live in `CONTRIBUTOR_LADDER.md`. +- **Voting**: Consensus-first. Voting fallback identical to GUAC (one vote, simple majority with 50% quorum, 2/3 of entire TSC for amendments/license exceptions). Deadlocks escalate to LF Projects Series Manager. +- **Chair**: Optional. Same posture as GUAC. +- **Meetings**: Public; 2nd Friday 11:00 ET and 4th Friday 10:00 ET monthly; notes in public Google Docs; mailing list + Slack. + +### Shared substrate + +Both projects use the **LF Projects Technical Charter** template verbatim (Sections 1-8: Mission, TSC, Voting, Compliance, Community Assets, General Rules, IP Policy, Amendments). License stack is Apache-2.0 code, CC-BY-4.0 docs, CDLA-Permissive-2.0 data, DCO required. CoC fallback to LF Projects CoC if no project-specific CoC exists. + +## Decisions + +### D1 -- Governance tier structure + +- **Decision**: Single-tier (gittuf-shape). +- **Rationale**: darnit is one product/repo today. GUAC's two-tier shape exists because it stewards multiple Core Projects (GUAC, Trustify). Adopting two-tier prematurely would require defining sub-project semantics that don't yet exist. +- **Alternatives considered**: GUAC-style two-tier; rejected because there's no sub-project today. The charter's amendment clause provides a path to two-tier in a future version if darnit grows siblings. + +### D2 -- Founding roster size & balance + +- **Decision**: Two founding members -- Michael Lieberman (Kusari, industry, @mlieberman85) and Justin Cappos (NYU, academia, @JustinCappos). Industry/academia tag + GitHub handle inline per gittuf precedent. +- **Rationale**: User-supplied. The split signals diversity intent on day one (the same tag convention gittuf uses for its 5-person roster). Recruiting a third member to restore meaningful quorum is recorded as a near-term action in the spec assumptions. +- **Alternatives considered**: Recruit a third member before launching the charter; rejected because the charter is needed now and the transitional two-member posture is explicitly accepted. + +### D3 -- Diversity guard mechanism + +- **Decision**: Transparency-by-labelling (gittuf-style). The roster columns `affiliation` and `category [industry|academia]` surface concentration risk; no hard ">=N different employers" quota is imposed by the charter. +- **Rationale**: A quota with only two members is either trivial (already satisfied 1:1) or coercive (would force structure on the next hire). Transparency lets the community judge concentration without binding future TSC composition decisions. +- **Alternatives considered**: GUAC's "at least 2 different employers" rule; rejected because it adds rigidity that pays off mainly at GUAC's larger roster size and tier complexity. + +### D4 -- Vote recording mechanism *(clarified in spec session 2026-06-17)* + +- **Decision**: GitHub PR approvals on the affected file are the canonical vote record for file-bound decisions (roster, charter, policy). For decisions without a file artifact, a GitHub Issue or Discussion with explicit `+1`/`-1`/`+0` comments from TSC members serves the same role. +- **Rationale**: Aligns with gittuf's operating practice, keeps the audit trail in git (immutable, DCO-signed), uses tooling darnit already runs on, and avoids creating a meetings infrastructure dependency on day one. PR review state is also queryable by the GitHub API for future automation. +- **Alternatives considered**: + - *Public meeting minutes as canonical* (closer to GUAC's `meetings/` directory): rejected because it presumes a meeting cadence darnit hasn't established and a notes-keeping role nobody is yet assigned. + - *Hybrid (PR for routine, minuted meeting for amendments)*: rejected as a needless dual-track. The charter's 2/3 supermajority for amendments + PR approvals on the charter file already provides the same auditability. + +### D5 -- Charter location + +- **Decision**: Charter and roster live at the top of the main `kusari-oss/darnit` repository -- `CHARTER.md`, `TECHNICAL-STEERING-COMMITTEE.md`, with a thin `GOVERNANCE.md` discoverability index. No separate `kusari-oss/darnit-community` governance repo at v1. +- **Rationale**: Both reference projects host governance in a separate community repo, but that separation makes sense at their scale (multiple maintained repos, working groups, meetings infrastructure). darnit has one repo. A separate community repo creates discoverability friction with no compensating benefit at v1. +- **Alternatives considered**: Separate community repo from day one (GUAC/gittuf pattern); rejected as premature. The charter's amendment clause lets a future TSC vote in a community-repo split when the project's structure warrants it. + +### D6 -- Removal-for-cause threshold *(clarified in spec session 2026-06-17)* + +- **Decision**: Majority of the *other* current TSC members; the member under review does not vote on their own removal. Same level as ordinary decisions (not a supermajority). +- **Rationale**: gittuf's exact rule. Self-recusal removes the most obvious conflict; a supermajority on top would create a tractable veto for any 1-of-3 member to block their own removal. +- **Alternatives considered**: + - *Supermajority (2/3 of other members)*: rejected because at small TSC sizes (2-4) the supermajority and simple majority of others are arithmetically identical or near-identical; complexity without benefit. + - *Unanimous of other members*: rejected because it gives any single other member veto power over a removal, which inverts the concentration concern the rule is meant to address. +- **Known consequence**: In the founding two-member regime, a majority of "the other members" means a majority of one -- a single member alone can effect a removal. This is recorded as an edge case in the spec and is one driver for the "recruit a third member promptly" near-term action. + +### D7 -- Definition of "inactivity" *(clarified in spec session 2026-06-17)* + +- **Decision**: No fixed numeric threshold. Inactivity is a discretionary judgment by the remaining TSC members, initiated via a public issue or PR and resolved by the removal-for-cause threshold (D6). +- **Rationale**: gittuf's posture. Numeric thresholds (e.g., GUAC's ">3 months") look objective but are gameable (lurking with one comment per quarter) and brittle (a maintainer with a documented sabbatical isn't actually inactive). A discretionary call with a public paper trail (issue/PR + threshold vote) gives the same auditability without the false precision. +- **Alternatives considered**: + - *GUAC's ">3 months" rule*: rejected as false precision; encodes a single shape of inactivity (no comments) and misses others. + - *Time + activity composite (e.g., "no PR review or vote in 6 months")*: rejected as premature optimization for a TSC that hasn't yet hit its first inactive-member case. + +### D8 -- Chair election + +- **Decision**: Optional. May be elected by simple majority; serves until resignation or replacement. No requirement to have a chair at v1. +- **Rationale**: gittuf precedent. With two founding members, electing a chair adds ceremony without function. Foundation liaison can be designated ad-hoc by simple majority on the rare occasions it's needed. +- **Alternatives considered**: Mandatory chair from day one; rejected as overhead for a two-member TSC. + +### D9 -- License of the charter document + +- **Decision**: CC-BY-4.0. +- **Rationale**: Matches both reference projects and the LF Projects governance doc convention. Permissive enough that downstream projects can fork the charter as a template. +- **Alternatives considered**: Apache-2.0 (code-style license on a doc -- semantically awkward); CC0 (waives attribution, which is incompatible with the "derived from LF Projects template" provenance). + +### D10 -- Code of Conduct posture + +- **Decision**: The charter names the project Code of Conduct as the governing CoC if one exists at the time the charter merges; otherwise the LF Projects CoC applies by default. The CoC itself is **out of scope** for this feature. +- **Rationale**: A CoC is a separate document with its own review and adoption cycle (often by the broader community, not just the TSC). Bundling it into this PR would slow the charter without changing the substantive governance. +- **Alternatives considered**: Author a project-specific CoC in the same PR; rejected as scope creep. A follow-on feature can adopt the Contributor Covenant or an LF-aligned CoC. + +## Open items deferred to `/speckit-tasks` + +None. All ambiguities were resolved in the spec clarification session. The remaining decisions are formatting and ordering choices best made during charter drafting (Phase 2 -- `/speckit-tasks`), not architectural research questions. diff --git a/specs/015-tsc-charter/spec.md b/specs/015-tsc-charter/spec.md new file mode 100644 index 0000000..e8d7f83 --- /dev/null +++ b/specs/015-tsc-charter/spec.md @@ -0,0 +1,123 @@ +# Feature Specification: Technical Steering Committee Charter + +**Feature Branch**: `015-tsc-charter` + +**Created**: 2026-06-17 + +**Status**: Draft + +**Input**: User description: "I want to draft up real quick a technical steering committee charter and list of people in it. It should follow a similar pattern the technical steering committee that GUAC has and gittuf has. The people who belong to that steering committee first should be Michael Lieberman (Kusari, industry, @mlieberman85) and Justin Cappos (New York University, academia, @JustinCappos)." + +## Clarifications + +### Session 2026-06-17 + +- Q: How are TSC votes mechanically recorded and made auditable? -> A: GitHub PR approvals on the affected file (roster, charter, policy) are the canonical vote record; for decisions without a file artifact, a GitHub Issue/Discussion with explicit "+1/-1" approval comments from TSC members serves the same role. Mirrors gittuf's pattern. +- Q: What is the threshold for removal-for-cause, and how is "inactivity" defined? -> A: Apply gittuf's defaults for both. Removal-for-cause requires majority approval of the *other* TSC members (the member under review does not vote on their own removal), at the same level as ordinary decisions rather than a supermajority. Inactivity is NOT defined by a fixed numeric threshold; it is a discretionary judgment by the remaining TSC members, initiated via a public issue or PR and resolved by the removal-for-cause threshold above. + +### Session 2026-06-18 + +- Q: Has the founding TSC roster changed before adoption? -> A: Yes. Two additional members are being seated before the charter merges: Stephen Augustus (Bloomberg, industry, @justaugustus) and Adolfo Garcia Veytia (Carabiner, industry, @puerco). This brings the founding TSC to four members and eliminates the transitional two-member concentration risk previously captured in `CHARTER.md` 2.6 and in the spec's edge cases / assumptions. `CHARTER.md` 2.6 has been removed accordingly; the edge cases and assumption about the two-member regime are preserved below for audit-trail purposes but marked as moot. + +## User Scenarios & Testing *(mandatory)* + +### User Story 1 - Published charter establishes governance authority (Priority: P1) + +A new contributor, downstream consumer, or OpenSSF/LF representative needs to know who is empowered to make binding technical decisions for the darnit project, how they got there, and how they can be removed. They open the charter in the repo and find a clear, self-contained document modeled on the LF Projects Technical Charter pattern used by GUAC and gittuf. + +**Why this priority**: Without a published charter, the project has no documented authority structure. This is the minimum viable artifact -- even with no other governance scaffolding (working groups, sub-projects, meeting cadence), a charter + roster lets the project make binding decisions, accept upstream/foundation engagement, and demonstrate that maintenance is not a single person. + +**Independent Test**: A reader unfamiliar with the project can answer, from the charter alone, the following questions: Who is on the TSC today? What is the TSC's scope? How are decisions made? How are members added and removed? What is the escalation path? + +**Acceptance Scenarios**: + +1. **Given** the charter is published at a discoverable path in the repository, **When** a reader opens it, **Then** they find the TSC's purpose, current roster with affiliations, voting rules, and amendment process without needing to consult external documents. +2. **Given** a reader is comparing darnit's governance to GUAC's and gittuf's, **When** they read the charter, **Then** they recognize the same LF-template structure (Mission, TSC, Voting, Compliance, Community Assets, General Rules, IP Policy, Amendments) so foundation reviewers and adopters can map it onto familiar precedent. + +--- + +### User Story 2 - Initial roster reflects industry + academia balance (Priority: P1) + +The community and foundation reviewers need to see that the TSC is not single-vendor controlled. The initial roster lists Michael Lieberman (Kusari, industry) and Justin Cappos (New York University, academia), each tagged with affiliation and GitHub handle in the same machine-readable style gittuf uses. + +**Why this priority**: The two founding members and their industry/academia split are the explicit ask. Mirroring gittuf's roster format (affiliation + industry/academia tag) signals diversity intent on day one even though the charter does not impose a hard quota. + +**Independent Test**: The roster file or roster section can be parsed by a human or trivial script to extract `(name, affiliation, category, github_handle)` for every member. + +**Acceptance Scenarios**: + +1. **Given** the roster is published, **When** a reader inspects it, **Then** they see Michael Lieberman tagged as Kusari/industry/@mlieberman85 and Justin Cappos tagged as NYU/academia/@JustinCappos. +2. **Given** a future member needs to be added, **When** a maintainer follows the membership change process from the charter, **Then** the roster format makes it obvious how to insert a new row without restructuring the document. + +--- + +### User Story 3 - Membership changes have a documented, auditable process (Priority: P2) + +A maintainer wants to propose adding a new TSC member, or a member wants to step down. The charter spells out the mechanism (who initiates, who votes, what threshold, what notification window) so the change can be made via a PR with a clear approval path rather than ad-hoc decision-making. + +**Why this priority**: Without this, the founding roster ossifies and every membership change becomes a one-off debate. It is not P1 because the charter is still useful at v1 with just the addition/removal rules from the LF template -- but documenting it explicitly is what makes the governance actually run. + +**Independent Test**: Given the charter, a maintainer can write a PR that adds or removes a TSC member and point to the exact charter clauses that authorize the change. + +**Acceptance Scenarios**: + +1. **Given** an existing TSC member nominates a candidate, **When** the charter's membership process is followed, **Then** the outcome (approved/rejected) is determined by an explicit voting rule and the change is recorded by editing the roster file. +2. **Given** a TSC member has been inactive, **When** the charter's removal process is invoked, **Then** the criteria for inactivity and the required approval threshold are both unambiguous from the charter text. + +--- + +### Edge Cases + +- **Two-member quorum** (moot as of 2026-06-18 -- the founding TSC was expanded to four members before adoption; preserved for audit-trail purposes): With only two founding members, a 50% quorum / majority rule means a single member can carry a vote. The charter should either (a) accept this as a transitional posture until the TSC grows, or (b) require unanimity from the founding members until a third member joins. The default chosen here is (a) with an explicit assumption that the TSC will recruit a third member promptly; see Assumptions. +- **Affiliation drift**: If a member's employer changes such that the industry/academia balance flips, the roster must be updated, but the charter does not force resignation. The roster's affiliation column is the source of truth. +- **Tie votes**: With an even number of members and no chair tiebreaker, a tie on a non-amendment vote means the motion fails. Amendments and license exceptions already require a two-thirds supermajority, which is unaffected. +- **Removal-for-cause in a two-member TSC** (moot as of 2026-06-18 -- see "Two-member quorum" above): Under FR-006, the member under review does not vote on their own removal, so a majority of the *other* members means a majority of one -- i.e., the remaining member alone can effect a removal. This is a known concentration risk of the gittuf-aligned threshold while the TSC has only two members and is one of several reasons the spec assumes a third member will be recruited promptly. The risk is accepted at v1 as a transitional posture rather than mitigated with a bespoke two-member supermajority rule. +- **Chair vacancy**: The charter permits but does not require a chair. If no chair is elected, the TSC operates without one; foundation liaison falls to any member designated by simple majority on an ad-hoc basis. +- **External escalation**: If the TSC deadlocks or quorum cannot be reached for an extended period, the LF Projects Series Manager / OpenSSF TAC is the escalation path, per the LF template. + +## Requirements *(mandatory)* + +### Functional Requirements + +- **FR-001**: The repository MUST contain a TSC charter document that follows the LF Projects Technical Charter template structure used by GUAC and gittuf, with sections covering Mission/Scope, TSC composition and authority, Voting & decision-making, Compliance/CoC, Community assets, General rules, IP policy, and Amendments. +- **FR-002**: The charter MUST list the initial TSC roster with: full name, affiliation, industry-or-academia tag, and GitHub handle, formatted in the same row-per-member style as gittuf's `TECHNICAL-STEERING-COMMITTEE.md`. The initial roster MUST include Michael Lieberman (Kusari, industry, @mlieberman85) and Justin Cappos (New York University, academia, @JustinCappos). +- **FR-003**: The charter MUST define the TSC's scope of authority, explicitly enumerating: setting technical direction; approving releases and security policy; managing sub-projects/working groups; appointing representatives to upstream foundations; and amending the charter itself. +- **FR-004**: The charter MUST specify the decision-making process as consensus-first with a voting fallback. Voting fallback MUST define: one vote per voting member; 50% quorum; simple majority of attendees with quorum for ordinary decisions; two-thirds of the entire TSC for charter amendments and license exceptions. +- **FR-005**: The charter MUST define the membership change process: how a candidate is nominated, who votes, the approval threshold, and how the change is recorded (i.e., a PR editing the roster file). +- **FR-006**: The charter MUST define a removal process covering both voluntary resignation and removal for cause (including inactivity). For removal-for-cause, the approval threshold MUST be a majority of the *other* current TSC members; the member under review MUST NOT vote on their own removal. Inactivity for the purposes of removal-for-cause MUST NOT be defined by a fixed numeric threshold (e.g., a specific number of months); it is a discretionary judgment by the remaining TSC members, initiated via a public issue or PR and resolved by the removal-for-cause threshold. +- **FR-007**: The charter MUST identify the project Code of Conduct that applies to TSC members and the fallback CoC (the LF Projects CoC) if no project-specific CoC has been adopted. +- **FR-008**: The charter MUST state the licensing posture for code (Apache-2.0), documentation (CC-BY-4.0), and data (CDLA-Permissive-2.0) consistent with GUAC and gittuf, and MUST require DCO sign-off on contributions. +- **FR-009**: The charter MUST be licensed under CC-BY-4.0 and that license MUST be stated in or alongside the document itself. +- **FR-010**: The charter MUST describe how it is amended, with the amendment threshold matching the two-thirds supermajority of the entire TSC defined in FR-004. +- **FR-011**: The roster MUST be structured so that adding or removing a member is a single localized edit (one row added/removed) requiring no restructuring of surrounding prose. +- **FR-012**: The charter MUST be discoverable from the repository root -- either by living at a conventional top-level path (e.g., `CHARTER.md`, `GOVERNANCE.md`) or by being linked from the README and/or a top-level `GOVERNANCE.md` pointer. +- **FR-013**: The charter MUST identify the canonical record of a TSC vote. For decisions that modify a tracked file (the roster, the charter itself, or any other policy file in the repository), the GitHub Pull Request approvals on that file ARE the vote record and MUST satisfy the thresholds in FR-004. For decisions that do not modify a file (e.g., approving a representative, endorsing an external statement), a GitHub Issue or Discussion thread containing explicit `+1` / `-1` / `+0` comments from TSC members serves the same role and MUST be linked from any subsequent artifact that depends on the decision. + +### Key Entities + +- **Charter**: The governing document. Contains the full LF-template-style text. Single canonical copy in the repository. +- **TSC Roster**: The ordered list of current TSC members. Each entry records: `(name, affiliation, category [industry|academia], github_handle)`. May live inside the charter or as a sibling file (`TECHNICAL-STEERING-COMMITTEE.md`) that the charter references. +- **TSC Member**: A natural person with one vote on TSC matters. Identified by GitHub handle for action attribution (PR approvals, votes recorded in issues). +- **Affiliation**: The organization a TSC member is associated with for the purpose of disclosure. Used to surface concentration risk (e.g., single-employer dominance) even though the v1 charter does not impose a hard quota. + +## Success Criteria *(mandatory)* + +### Measurable Outcomes + +- **SC-001**: A reader unfamiliar with the project can identify the current TSC members and the rule for changing membership in under 2 minutes from landing on the repository root. +- **SC-002**: The charter passes a structural diff against the LF Projects Technical Charter template: all eight canonical sections (Mission, TSC, Voting, Compliance, Community Assets, General Rules, IP Policy, Amendments) are present and ordered as in the template. +- **SC-003**: 100% of TSC members in the roster have all four required fields populated (name, affiliation, category, GitHub handle). +- **SC-004**: A maintainer can execute a hypothetical membership change (add or remove a member) by editing exactly one file in a single PR, with the charter clauses they're invoking citable by section reference. +- **SC-005**: The charter is internally consistent: every voting threshold mentioned in narrative text matches the numeric thresholds defined in the Voting section (no contradictions between, e.g., "majority" in one place and "two-thirds" in another for the same action). + +## Assumptions + +- **Single-tier governance**: Darnit is presently a single project, so the charter mirrors gittuf's single-tier (TSC over one project) rather than GUAC's two-tier (Steering Committee over multiple Core Projects). Should darnit later grow sibling sub-projects, a future amendment can introduce the two-tier shape. +- **Charter location**: The charter lives in the main `kusari-oss/darnit` repository at a top-level path (e.g., `GOVERNANCE.md` or `CHARTER.md` with the roster either embedded or as a sibling `TECHNICAL-STEERING-COMMITTEE.md`). No separate `community` governance repo is created at v1. +- **Transitional two-member TSC** (resolved 2026-06-18 -- the founding TSC was expanded to four members before adoption, restoring meaningful quorum): With only two founding members, the 50%-quorum / majority-of-attendees rule technically allows a single member to carry a vote. This is accepted as a transitional posture; the TSC is expected to recruit a third member promptly to restore meaningful quorum, and the charter notes this as a near-term action rather than a permanent regime. +- **No fixed terms, no chair required**: Following gittuf's pattern, members serve until resignation or removal; no fixed term lengths. A chair MAY be elected but is not required at v1. +- **Diversity by transparency, not quota**: Following gittuf's pattern of labelling affiliation + industry/academia in the roster, rather than GUAC's hard "at least two different employers" rule. Concentration risk is surfaced rather than enforced. +- **License of the charter itself**: CC-BY-4.0, consistent with both reference projects' governance documents. +- **CoC**: Project will adopt a CoC consistent with OpenSSF/LF norms; if none is present at the time the charter merges, the LF Projects CoC applies by default. +- **Foundation alignment**: The charter is written so that it can be submitted to OpenSSF / LF Projects without structural changes if darnit chooses formal foundation hosting in the future, but the charter does not presume that hosting has happened. +- **Out of scope for this spec**: Drafting the project Code of Conduct, defining a Contributor Ladder, scheduling community meetings, or creating a separate governance repository. Each of these is a logical follow-on once the charter is in place. diff --git a/specs/015-tsc-charter/tasks.md b/specs/015-tsc-charter/tasks.md new file mode 100644 index 0000000..98dd101 --- /dev/null +++ b/specs/015-tsc-charter/tasks.md @@ -0,0 +1,193 @@ +--- + +description: "Task list for authoring the darnit Technical Steering Committee charter and roster." +--- + +# Tasks: Technical Steering Committee Charter + +**Input**: Design documents from `/specs/015-tsc-charter/` + +**Prerequisites**: plan.md, spec.md, research.md, data-model.md, quickstart.md (all present) + +**Tests**: Not requested. This feature ships Markdown only -- validation is done by running the data-model.md validation rules and the spec checklist against the authored files (bundled into Phase 6: Polish), not by a unit-test framework. + +**Organization**: Tasks are grouped by user story so each story (US1, US2, US3) can be authored and validated independently. + +## Format: `[ID] [P?] [Story] Description` + +- **[P]**: Can run in parallel (different files, no dependencies on incomplete tasks). +- **[Story]**: Maps the task to a user story from `spec.md`. Setup/Foundational/Polish phases carry no story label. +- All file paths are repository-root relative. + +## Path Conventions + +This feature is a documentation deliverable, not code. There is no `src/` or `tests/` tree. Files live at the **repository root** (`/Users/mlieberman/Projects/darnit/`): `CHARTER.md`, `TECHNICAL-STEERING-COMMITTEE.md`, `GOVERNANCE.md`, and a one-line edit to the existing `README.md`. The plan in `specs/015-tsc-charter/plan.md` documents this structure decision. + +--- + +## Phase 1: Setup + +**Purpose**: Confirm the branch is in the right state to author the three top-level governance files. + +- [X] T001 Verify the current branch is `015-tsc-charter` and the working tree is clean (`git status` shows only the spec files already committed for this feature) +- [X] T002 Confirm no `CHARTER.md`, `TECHNICAL-STEERING-COMMITTEE.md`, or `GOVERNANCE.md` already exist at the repository root (`ls -la CHARTER.md TECHNICAL-STEERING-COMMITTEE.md GOVERNANCE.md`); if any exist, stop and reconcile rather than clobber +- [X] T003 [P] Open `https://github.com/gittuf/community/blob/main/CHARTER.md` (or equivalent local copy) to source the LF Projects Technical Charter section structure and language for adaptation in Phase 3 + +--- + +## Phase 2: Foundational + +**Purpose**: One blocking decision the rest of the charter and roster reference. + +**CRITICAL**: No user story work begins until this is done. + +- [X] T004 Record the canonical adopted date as `2026-06-17` (ISO-8601), to be used consistently in `CHARTER.md` document metadata and the `TECHNICAL-STEERING-COMMITTEE.md` header comment + +**Checkpoint**: Adopted date fixed; US1, US2, and US3 can now proceed (US1 and US2 in parallel; US3 follows US1). + +--- + +## Phase 3: User Story 1 -- Published charter establishes governance authority (Priority: P1) [MVP] + +**Goal**: Produce `CHARTER.md` at the repository root with the full LF Projects Technical Charter section structure (Sections 1-8) used by GUAC and gittuf, with all required content per FR-001, FR-003, FR-004, FR-007, FR-008, FR-009, FR-010, FR-013. + +**Independent Test**: A reader unfamiliar with the project opens `CHARTER.md` and can answer, from that file alone: What is the TSC's scope? How are decisions made? How are votes recorded? Under what license is the document released? They do not need to consult external documents to find these answers (SC-001, SC-002). + +### Implementation for User Story 1 + +- [X] T005 [US1] Create `/Users/mlieberman/Projects/darnit/CHARTER.md` with Section 1 (Mission and Scope of the Project): one paragraph naming darnit's mission (AI-assisted compliance auditing with a plugin architecture) and the TSC's scope of authority per FR-003 (technical direction, releases, security policy, sub-projects/working groups, foundation representation, charter amendments) +- [X] T006 [US1] Add Sections 2 (Technical Steering Committee) and 3 (TSC Voting) to `CHARTER.md`. Section 2: single-tier composition (per D1), pointer to `TECHNICAL-STEERING-COMMITTEE.md` for the live roster, chair clause (optional per D8); leave the *membership change* and *removal-for-cause* narrative as an explicit `` placeholder for tasks T010-T012. Section 3: full FR-004 voting thresholds (consensus-first; one vote per member; 50% quorum; simple majority of attendees with quorum for ordinary decisions; 2/3 of entire TSC for charter amendments and license exceptions) AND the FR-013 vote recording mechanism (GitHub PR approvals on the affected file are the canonical record; non-file decisions use a GitHub Issue/Discussion with explicit `+1`/`-1`/`+0` comments from TSC members) +- [X] T007 [US1] Add Sections 4 (Compliance with Policies), 5 (Community Assets), 6 (General Rules and Operations), 7 (Intellectual Property Policy), and 8 (Amendments) to `CHARTER.md`, adapting language verbatim from the LF Projects Technical Charter where possible. Section 4: name the project Code of Conduct, fall back to the LF Projects CoC if none exists yet (per D10 / FR-007), require DCO sign-off (per FR-008). Section 7: state the license stack -- code Apache-2.0, docs CC-BY-4.0, data CDLA-Permissive-2.0 (per FR-008). Section 8: amendment process with 2/3-of-entire-TSC threshold (per FR-010, referencing the threshold defined in Section 3) +- [X] T008 [US1] Add document metadata to `CHARTER.md`: an "Adopted: 2026-06-17" line, a provenance line ("Adapted from the LF Projects Technical Charter, also used by GUAC and gittuf"), and an explicit "This document is licensed under CC-BY-4.0." notice (per FR-009) + +**Checkpoint**: `CHARTER.md` contains all 8 LF sections in order, with the membership process deliberately stubbed out for US3. Validation rule "all eight sections present in order" from `data-model.md` should already pass. + +--- + +## Phase 4: User Story 2 -- Initial roster reflects industry + academia balance (Priority: P1) + +**Goal**: Produce `TECHNICAL-STEERING-COMMITTEE.md` at the repository root with the row-per-member Markdown table format mirroring gittuf, populated with the two founding members. + +**Independent Test**: A human or trivial script can parse the file's table and extract `(name, affiliation, category, github_handle)` for both members. The roster row for Michael Lieberman shows Kusari / industry / @mlieberman85; the row for Justin Cappos shows New York University / academia / @JustinCappos (SC-003). + +### Implementation for User Story 2 + +- [X] T009 [P] [US2] Create `/Users/mlieberman/Projects/darnit/TECHNICAL-STEERING-COMMITTEE.md` exactly per the "Required document structure" block in `specs/015-tsc-charter/data-model.md`: H1 ("# Technical Steering Committee"), an HTML comment with `Adopted: 2026-06-17. License: CC-BY-4.0.`, an introductory sentence, the Markdown table with all five columns (`Name`, `Affiliation`, `Category`, `GitHub`, `Role`), the two founding-member rows (Michael Lieberman | Kusari | industry | @mlieberman85 | member; Justin Cappos | New York University | academia | @JustinCappos | member), and a closing sentence linking to `./CHARTER.md` + +**Checkpoint**: Roster file is independently parseable; all four required columns populated for every row (data-model.md validation rule); SC-003 satisfied. + +**Note**: T009 is parallelizable with all of Phase 3 -- it touches a different file from `CHARTER.md`. + +--- + +## Phase 5: User Story 3 -- Membership changes have a documented, auditable process (Priority: P2) + +**Goal**: Replace the `` placeholder in `CHARTER.md` Section 2 with the full membership-change and removal-for-cause narrative, satisfying FR-005, FR-006, FR-011. + +**Independent Test**: A maintainer reading `CHARTER.md` Section 2 alone can write a PR that adds or removes a TSC member and point to the exact section text that authorizes the change and defines the approval threshold. + +### Implementation for User Story 3 + +- [X] T010 [US3] In `/Users/mlieberman/Projects/darnit/CHARTER.md` Section 2, replace the `` placeholder with the membership-addition process: a candidate is nominated by an existing TSC member via a PR that adds a row to `TECHNICAL-STEERING-COMMITTEE.md`; existing TSC members vote by approving (or declining) the PR; approval requires a majority of existing TSC members; the merge commit is the canonical record per FR-013 +- [X] T011 [US3] In the same Section 2, add the removal process: voluntary resignation is a PR removing the member's row (no vote required, acknowledgment by another TSC member suffices). Removal-for-cause requires a majority of the *other* current TSC members -- the member under review does not vote on their own removal (per FR-006). Explicitly state that "inactivity" is NOT defined by a fixed numeric threshold; it is a discretionary judgment by the remaining TSC members, initiated via a public issue or PR and resolved by the removal-for-cause threshold above +- [X] T012 [US3] In the same Section 2, add a brief acknowledgement of the two-member-TSC concentration risk: while the TSC has only two voting members, "majority of the other members" arithmetically means a majority of one, so a remaining member alone can effect a removal. This is a known transitional posture and the project intends to recruit a third member promptly. Reference the corresponding edge case in `specs/015-tsc-charter/spec.md` is NOT required (the charter must stand on its own), but the *substance* of the edge case MUST appear in the charter text + +**Checkpoint**: `CHARTER.md` is now content-complete. The spec checklist item "All functional requirements have clear acceptance criteria" should be re-verifiable end-to-end. + +--- + +## Phase 6: Polish & Cross-Cutting + +**Purpose**: Add the discoverability layer (GOVERNANCE.md, README link), then validate the deliverable against the spec checklist, the data-model validation rules, and the constitution's Development Workflow gates. + +- [X] T013 [P] Merge with pre-existing `/Users/mlieberman/Projects/darnit/GOVERNANCE.md` (committed 2026-01-15 in commit `64dd2f2`) rather than create a new file. **Reconciliation chosen interactively during implementation**: the existing maintainer-only decision-making model was reframed as the operational layer *below* the TSC charter -- top of document points to `CHARTER.md` and `TECHNICAL-STEERING-COMMITTEE.md` for binding governance rules; existing Project Structure, Roles and Responsibilities, Day-to-Day PR Process, Release Process, Code of Conduct, and Contact sections preserved with light edits noting that TSC authority sits above maintainer authority. Note: the data-model.md "<=30 lines" target was deliberately exceeded -- the merged document is ~70 lines because it had to retain pre-existing content; this is a deliberate deviation from the plan, not a defect. +- [X] T014 [P] Edit `/Users/mlieberman/Projects/darnit/README.md` to add a one-line "Governance" link pointing to `./GOVERNANCE.md`, placed near the top or in an existing "Project Info" / "Community" section (whichever exists); this satisfies the "linked from the README" alternative in FR-012 +- [X] T015 Run the data-model.md validation rules against the three new files: (a) `CHARTER.md` contains all 8 LF sections in order (`grep -nE "^## " CHARTER.md`); (b) `grep -n "NEEDS CLARIFICATION" CHARTER.md TECHNICAL-STEERING-COMMITTEE.md GOVERNANCE.md` returns nothing; (c) every roster row has all four required columns populated; (d) every `GitHub` cell matches `@[A-Za-z0-9-]+`; (e) at most one row carries `Role = chair`; (f) `CHARTER.md` contains the string `CC-BY-4.0`; (g) cross-document invariant -- neither founding member's GitHub handle appears in `CHARTER.md` (only in the roster), so a future roster change requires editing one file +- [X] T016 Re-run the spec quality checklist at `specs/015-tsc-charter/checklists/requirements.md` against the authored files; confirm every item still passes (especially "Requirements are testable and unambiguous", "Success criteria are measurable", "No implementation details leak into specification") +- [X] T017 Walk through `specs/015-tsc-charter/quickstart.md` "Sanity check before submitting any governance PR" against the PR diff, before opening the PR +- [X] T018 Run the constitution's Development Workflow gates: `uv run ruff check .` (no-op on Markdown but must still pass), `uv run pytest tests/ --ignore=tests/integration/ -q` (unchanged behavior; must pass), `uv run python scripts/validate_sync.py --verbose` (this feature does not touch the framework-design spec, so sync should remain valid) + +--- + +## Dependencies & Execution Order + +### Phase Dependencies + +- **Setup (Phase 1)**: No dependencies; start immediately. +- **Foundational (Phase 2)**: Depends on Setup. Blocks all user stories. +- **User Story 1 (Phase 3)**: Depends on Foundational. Authors `CHARTER.md` skeleton + Sections 3-8. +- **User Story 2 (Phase 4)**: Depends on Foundational. Authors `TECHNICAL-STEERING-COMMITTEE.md`. **Independent of US1** (different file). +- **User Story 3 (Phase 5)**: Depends on US1 (T006 creates the placeholder T010-T012 replace). +- **Polish (Phase 6)**: T013 and T014 can start anytime after Foundational (T013 doesn't depend on any other file's contents; T014 is a separate file). T015-T018 (validation) depend on all of US1, US2, US3 being complete. + +### User Story Dependencies + +- **US1 (P1)**: Depends only on Foundational. +- **US2 (P1)**: Depends only on Foundational. Parallelizable with US1. +- **US3 (P2)**: Depends on US1 (specifically T006). Cannot start until T006 is done. + +### Within Each User Story + +- US1 is a sequential edit chain (all tasks touch the same file): T005 -> T006 -> T007 -> T008. +- US2 is a single task (T009). +- US3 is a sequential edit chain (all tasks touch the same file): T010 -> T011 -> T012. + +### Parallel Opportunities + +- **T003** (read reference template) [P] vs T001/T002 -- read-only, no file conflict. +- **T009** (US2, roster file) [P] vs all of US1 (T005-T008) -- different file. +- **T013** (GOVERNANCE.md) [P] vs T014 (README.md edit) -- different files; both can start once Foundational is done. +- US3 (T010-T012) cannot start in parallel with US1 because they edit the same file. + +--- + +## Parallel Example: After Foundational Completes + +```bash +# Start US1 (sequential, in one editor session): +T005 -> T006 -> T007 -> T008 -> CHARTER.md complete (with US3 placeholder) + +# In parallel (different files), can start at the same time as US1: +T009 # author TECHNICAL-STEERING-COMMITTEE.md +T013 # author GOVERNANCE.md +T014 # edit README.md + +# After US1 (T006 specifically) completes, start US3: +T010 -> T011 -> T012 -> CHARTER.md fully content-complete + +# After everything above, run validation: +T015 -> T016 -> T017 -> T018 +``` + +--- + +## Implementation Strategy + +### MVP First (US1 + US2) + +Both US1 and US2 are P1; the MVP is **both files** authored. Once T005-T009 are done, the project has a published charter and a published roster -- even without US3's membership-process narrative, the LF template plus a roster file is the minimum coherent governance artifact. + +1. Complete Phase 1: Setup. +2. Complete Phase 2: Foundational (T004). +3. Complete Phase 3 (US1, T005-T008) and Phase 4 (US2, T009) -- parallelize if working with two people; otherwise interleave by file. +4. **STOP and VALIDATE**: the two files exist, are internally consistent, and meet SC-001 / SC-002 / SC-003. If urgent (e.g., a foundation review tomorrow), this is shippable as v1.0 with US3 content as a follow-on PR. + +### Incremental Delivery + +1. Setup + Foundational -> ready to author. +2. US1 + US2 -> MVP charter + roster ship. +3. US3 -> membership-process narrative ships, completing FR-005 / FR-006. +4. Polish -> GOVERNANCE.md, README link, and final validation ship. + +### Single-Author Strategy (default for "real quick") + +One person, one editor session, in order: T001-T018 sequentially. The full set takes one focused session. + +--- + +## Notes + +- All tasks edit files **at the repository root**, not under `specs/015-tsc-charter/`. Spec-directory files (spec.md, plan.md, research.md, data-model.md, quickstart.md, tasks.md, checklists/) are *inputs*, not outputs of this task list. +- The single-author strategy is the intended default (matches the user's original "real quick" framing). +- No new runtime code, no new tests, no new CI. The constitution's Development Workflow gates (T018) must still pass because they run on every PR. +- Commit cadence: one commit per phase is reasonable; alternatively one commit per task for finer audit trail. The PR opening this branch is the one that records the TSC's first PR-as-vote-record on its own charter (a quietly recursive moment).