Skip to content

Commit

Permalink
Change to minimal license enforcement
Browse files Browse the repository at this point in the history
* This removes the license gem enitrely.
* Specifies the user to declare his compliance with either opensource or commercial usage.
  • Loading branch information
mbj committed Apr 8, 2024
1 parent b824f87 commit bce9323
Show file tree
Hide file tree
Showing 44 changed files with 722 additions and 1,666 deletions.
10 changes: 10 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
# v0.12.0 [unreleased]

Drop the license gem, entirely. This reduces DRM in mutants code base to the absolute minimal.
Mutant is *still* comercial software that requires payment if used on a commercial code base!

Migration:

* Commercial users: Add `usage: commercial` to your config file (or `--usage commercial` to your CLI)
* Opensource users: Add `usage: opensource` to your config file (or `--usage opensource` to your CLI)

# v0.11.34 2024-03-26

* [#1432](https://github.com/mbj/mutant/pull/1432)
Expand Down
8 changes: 1 addition & 7 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,18 +1,13 @@
PATH
remote: .
specs:
mutant (0.11.34)
mutant (0.12.0)
diff-lcs (~> 1.3)
parser (~> 3.3.0)
regexp_parser (~> 2.9.0)
sorbet-runtime (~> 0.5.0)
unparser (~> 0.6.9)

GEM
remote: https://oss:[email protected]/
specs:
mutant-license (0.1.1.2.2355046999240944981729280251890364410689.5)

GEM
remote: https://rubygems.org/
specs:
Expand Down Expand Up @@ -69,7 +64,6 @@ PLATFORMS

DEPENDENCIES
mutant!
mutant-license!
rspec (~> 3.10)
rspec-core (~> 3.10)
rspec-its (~> 1.3.0)
Expand Down
6 changes: 0 additions & 6 deletions Gemfile.shared
Original file line number Diff line number Diff line change
@@ -1,6 +0,0 @@
# Mutant itself uses an opensource license key.
# Scoped to https://github.com/mbj/mutant it'll
# not be useful elsewhere.
source 'https://oss:[email protected]' do
gem 'mutant-license'
end
60 changes: 17 additions & 43 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,54 +77,27 @@ Labels:

## Licensing

Mutant is commercial software, with a free usage plan for opensource projects.
Mutant is commercial software, with a free usage option for opensource projects.
Opensource projects have to be on a public repository.

Commercial projects have to acquire a license per developer, with unlimited repositories
per developer. CI usage for licensed developers is included.
Commercial projects have to pay a monthly or annual subscription fee.

Opensource projects have to acquire their free license per repository. That license will
work for any contributor implicitly. Typically the project maintainer gets the license.
## Opensource usage

The license distribution happens through the `mutant-license` gem. Mutant installs without
that dependency, but will not be very cooperative unless `mutant-license` is also available.
Usage is free and does not require a signup. But it requires the code is under an
opensource license and public. Specify `--usage opensource` on the CLI or `usage: opensource`
in the config file.

The license gem is dynamically generated per licensee and comes with a unique license gem source
URL.
## Commercial usage

After signup for a license the following has to be added to your `Gemfile` replacing `${key}`
with the license key and `${plan}` with `com` for commercial or `oss` for opensource usage.
Commercial use requires payment via a subscription and requires a signup. See [pricing](#pricing) for
available plans.

```ruby
source 'https://${plan}:${key}@gem.mutant.dev' do
gem 'mutant-license'
end
```

The mutant license gem contains metadata that allows mutant to verify licensed use.

For commercial licenses mutant checks the git commit author or the configured git email
to be in the set of licensed developers.

For opensource licenses mutant checks the git remotes against the licensed git repositories.
This allows the project maintainer to sign up and not bother collaborators with the details.

There are, apart from initial license gem installation, no remote interaction for
license validation.

### Getting an Opensource license

As stated above: Opensource projects of any kind are free to use mutant.

Just mail [me](mailto:[email protected]?subject=Mutant%20Opensource%20License): Please
include:

* Just the git remote URL of your repository. Repository can be anywhere, must not be on Github, just has to be public.

I do not need any more details.
After payment pecify `--usage commercial` on the CLI or `usage: commercial` in the config file.

### Pricing

**Mutant is free for [opensource use](#getting-an-opensource-license)!**
**Mutant is free for [opensource use](#opensource-usage)!**

For commercial use mutants pricing is subscription based.

Expand All @@ -137,18 +110,19 @@ For commercial use mutants pricing is subscription based.

Costs are **per developer using mutant on any number of repositories**.

Volume licenses with custom plans are available on request.
Volume subscriptions with custom plans are available on request.

Should you want to procure a commercial mutant subscription please [mail me](mailto:[email protected]?subject=Mutant%20Commercial%20License).
Should you want to procure a commercial mutant subscription please
[mail me](mailto:[email protected]?subject=Mutant%20Commercial%20License) to start the payment
process.

Please include the following information:

* Your business invoice address.
* A payment email address, if different from your email address.
* Only for the EU: A valid VAT-ID is *required*, no sales to private customers to avoid the
horrors cross border VAT / MOSS.
VAT for customers outside of Malta will use **reverse charging**.
* *Per developer* the git author email address as returned by `git config user.email`
VAT for EU customers outside of Malta will use **reverse charging**.

Also feel free to ask any other question I forgot to proactively answer here.

Expand Down
59 changes: 18 additions & 41 deletions docs/commercial.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ Is there a trial version?

There is no free trial.

But mutant offers to refund the last monthly
payment on cancellation. Basically a rolling trial on monthly plans.
But mutant offers to refund the last monthly payment on cancellation.
Basically a rolling trial on monthly plans.

Yearly and custom plans do not offer any refunds but come with discounts.

Expand Down Expand Up @@ -35,17 +35,14 @@ This per subscription is valid for any number of private repositories.

Depending on your plan subscriptions renew monthly or yearly.

After purchase you get access to a custom rubygem hosted on mutants license
server that enables mutants functionality in commercial repositories.

After purchase you setup the commercial usage type in mutant
and are ready to go.

How do I determine the number of required subscriptions?
--------------------------------------------------------

Collect the git author email from each of your developers that need to use mutant.
Use `git config --get user.email`. Count that list.

Mutant on CI will work on any commit authored by a developer in that list.
Use `git config --get user.email`. Count that list.

So a designer, who contributes to your repository, but never touches Ruby/Mutant:
Will not be forced to get a mutant subscription.
Expand All @@ -54,35 +51,12 @@ What happens if my subsription lapses?
--------------------------------------

If your credit card cannot be charged, even after retries: The subscription will be
considered inactive and you loose access to mutants license gem. Which prevents `bundle install`
and adjacent commands to succeed.
considered inactive and you loose the right to run mutant.

**Please note that pricing can chance**. Once you purchase a subscription, you get that price
forever **as long you pay on time**. If your subscription expires for a non-payment, you will lose
that pricing and need to repurchase at current pricing.

What does the license require me to do?
---------------------------------------

Your purchase gets you unique access credentials for accessing the license gem which enables
mutant on a private repository. The license requires you to keep these access credentials private.

If your access credentials are ever found to be publicized:

1. You get a warning email with details. You need to remove the content and
will get new new credentials being generated.
The old credentials will stop working immediately so you'll need to update your
`Gemfile`.
2. If your credentials are publicized a second time, we reserve the right to permanently
remove access (but won't unless it's really egregious - sloppy contractors happen).

Do I have to share the credentials with all of my developers?
-------------------------------------------------------------

In general yes. The intention is that the license details gets checked into the
`Gemfile`. This only gives access to mutants funcionality, your billing account is
separate and individuall developers cannot update the subscription.

Can I get a refund?
-------------------

Expand All @@ -98,7 +72,6 @@ Can I request a change to the license terms?
--------------------------------------------

Mutant is sold as is. Pricing becomes negotiatable over 20 developers.

License terms may be amended for even bigger customers.

Disputing a Charge
Expand Down Expand Up @@ -133,15 +106,8 @@ Schirp DSO LTD only collects enough customer information provide its services wh
* Per developer: The developers git author emaill address.
* Standard HTTP logging for the license server with 14d expiry.

Mutant runs exclusively on your developers machines. Or your CI. The only time mutant
calls a service operated by Schirp DSO LTD: Is on `bundle install`. Where `bundler` sends a
HTTP request with your license key to the license server.

BTW: As mutant does NOT control the HTTP call side (bundler does instead) there cannot be any
information leak being caused by mutant. Apart from HTTP logs at the license server.
Mutant runs exclusively on your developers machines. Or your CI.

At no point in time Schirp DSO LTD gets access to your source code, your customers data
or other sensitive material.

Should mutant gain more features that would enable features such as distributed
analysis and reporting, these features will be opt in, with a big warning.
Expand All @@ -153,3 +119,14 @@ Customer information is never shared or sold to anyone.
* Stripe for subscription, credit card and SEPA direct debits.
* Transferwise for receiving SEPA and ACH transfers.
* AWS to host the license server.

At no point in time Schirp DSO LTD gets access to your source code, your customers data
or other sensitive material.

### Pre mutant 0.12 license gem.

The only time mutant calls a service operated by Schirp DSO LTD: Is on `bundle install`.
Where `bundler` sends a HTTP request with your license key to the license server.

BTW: As mutant does NOT control the HTTP call side (bundler does instead) there cannot be any
information leak being caused by mutant. Apart from HTTP logs at the license server.
1 change: 1 addition & 0 deletions docs/mutant-minitest.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ This prints a report like:

```sh
Mutant environment:
Usage: opensource
Matcher: #<Mutant::Matcher::Config subjects: [AUOM*]>
Integration: Mutant::Integration::Minitest
Jobs: 8
Expand Down
1 change: 1 addition & 0 deletions docs/mutant-rspec.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ This prints a report like:

```sh
Mutant environment:
Usage: opensource
Matcher: #<Mutant::Matcher::Config subjects: [AUOM*]>
Integration: Mutant::Integration::Rspec
Jobs: 8
Expand Down
10 changes: 3 additions & 7 deletions lib/mutant.rb
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ module Mutant
require 'mutant/require_highjack'
require 'mutant/mutation'
require 'mutant/mutation/operators'
require 'mutant/usage'
require 'mutant/mutation/config'
require 'mutant/mutator'
require 'mutant/mutator/util'
Expand Down Expand Up @@ -221,7 +222,6 @@ module Mutant
require 'mutant/config/coverage_criteria'
require 'mutant/cli'
require 'mutant/cli/command'
require 'mutant/cli/command/subscription'
require 'mutant/cli/command/environment'
require 'mutant/cli/command/environment/irb'
require 'mutant/cli/command/environment/run'
Expand Down Expand Up @@ -255,11 +255,6 @@ module Mutant
require 'mutant/repository/diff/ranges'
require 'mutant/zombifier'
require 'mutant/range'
require 'mutant/license'
require 'mutant/license/subscription'
require 'mutant/license/subscription/commercial'
require 'mutant/license/subscription/opensource'
require 'mutant/license/subscription/repository'
require 'mutant/segment'
require 'mutant/segment/recorder'
end
Expand Down Expand Up @@ -363,7 +358,8 @@ class Config
matcher: Matcher::Config::DEFAULT,
mutation: Mutation::Config::EMPTY,
reporter: Reporter::CLI.build(WORLD.stdout),
requires: EMPTY_ARRAY
requires: EMPTY_ARRAY,
usage: Usage::Unknown.new
)
end # Config

Expand Down
10 changes: 1 addition & 9 deletions lib/mutant/cli/command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ def banner

def parse(arguments)
Either
.wrap_error(OptionParser::InvalidOption) { parser.order(arguments) }
.wrap_error(OptionParser::InvalidArgument, OptionParser::InvalidOption) { parser.order(arguments) }
.lmap(&method(:with_help))
.bind(&method(:parse_remaining))
end
Expand Down Expand Up @@ -176,14 +176,6 @@ def parse_remaining(remaining)
end
end

def parse_remaining_arguments(remaining)
if remaining.any?
Either::Left.new("#{full_name}: Does not expect extra arguments")
else
Either::Right.new(self)
end
end

def parse_subcommand(arguments)
command_name, *arguments = arguments

Expand Down
15 changes: 15 additions & 0 deletions lib/mutant/cli/command/environment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class Environment < self
add_integration_options
add_matcher_options
add_reporter_options
add_usage_options
].freeze

private
Expand Down Expand Up @@ -136,6 +137,20 @@ def add_reporter_options(parser)
set(reporter: @config.reporter.with(print_warnings: true))
end
end

def add_usage_options(parser)
parser.separator('Usage:')

parser.accept(Usage, Usage::CLI_REGEXP) do |value|
Usage.parse(value).from_right
end

parser.on(
'--usage USAGE_TYPE',
Usage,
'License usage: opensource|commercial'
) { |usage| set(usage: usage) }
end
end # Run
# rubocop:enable Metrics/ClassLength
end # Command
Expand Down
15 changes: 6 additions & 9 deletions lib/mutant/cli/command/environment/run.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,6 @@ class Run < self
SHORT_DESCRIPTION = 'Run code analysis'
SUBCOMMANDS = EMPTY_ARRAY

UNLICENSED = <<~MESSAGE.lines.freeze
You are using mutant unlicensed.
See https://github.com/mbj/mutant#licensing to aquire a license.
Note: Its free for opensource use, which is recommended for trials.
MESSAGE

NO_TESTS_MESSAGE = <<~'MESSAGE'
===============
Mutant found no tests available for mutation testing.
Expand All @@ -34,8 +27,8 @@ class Run < self
private

def action
License.call(world)
.bind { bootstrap }
bootstrap
.bind(&method(:verify_usage))
.bind(&method(:validate_tests))
.bind(&Mutation::Runner.public_method(:call))
.bind(&method(:from_result))
Expand All @@ -56,6 +49,10 @@ def from_result(result)
Either::Left.new('Uncovered mutations detected, exiting nonzero!')
end
end

def verify_usage(environment)
environment.config.usage.verify.fmap { environment }
end
end # Run
end # Environment
end # Command
Expand Down
Loading

0 comments on commit bce9323

Please sign in to comment.