Elixir v1.17 released: set-theoretic types in patterns, calendar durations, and Erlang/OTP 27 support

Elixir v1.17 has just been released. 🎉

This release introduces set-theoretic types into a handful of language constructs. While there are still many steps ahead of us, this important milestone already brings benefits to developers in the form of new warnings for common mistakes. This new version also adds support for Erlang/OTP 27, the latest and greatest Erlang release. You’ll also find a new calendar-related data type (Duration) and a Date.shift/2 function.

Let’s dive in.

Warnings from gradual set-theoretic types

This release introduces gradual set-theoretic types to infer types from patterns and use them to type check programs, enabling the Elixir compiler to find faults and bugs in codebases without requiring changes to existing software. The underlying principles, theory, and roadmap of our work have been outlined in “The Design Principles of the Elixir Type System” by Giuseppe Castagna, Guillaume Duboc, José Valim.

At the moment, Elixir developers will interact with set-theoretic types only through warnings found by the type system. The current implementation models all data types in the language:

  • binary(), integer(), float(), pid(), port(), reference() - these types are indivisible. This means both 1 and 13 get the same integer() type.

  • atom() - it represents all atoms and it is divisible. For instance, the atom :foo and :hello_world are also valid (distinct) types.

  • map() and structs - maps can be “closed” or “open”. Closed maps only allow the specified keys, such as %{key: atom(), value: integer()}. Open maps support any other keys in addition to the ones listed and their definition starts with ..., such as %{..., key: atom(), value: integer()}. Structs are closed maps with the __struct__ key.

  • tuple(), list(), and function() - currently they are modelled as indivisible types. The next Elixir versions will also introduce fine-grained support to them.

We focused on atoms and maps on this initial release as they are respectively the simplest and the most complex types representations, so we can stress the performance of the type system and quality of error messages. Modelling these types will also provide the most immediate benefits to Elixir developers. Assuming there is a variable named user, holding a %User{} struct with a address field, Elixir v1.17 will emit the following warnings at compile-time:

  • Pattern matching against a map or a struct that does not have the given key, such as %{adress: ...} = user (notice address vs adress).

  • Accessing a key on a map or a struct that does not have the given key, such as user.adress.

  • Invoking a function on non-modules, such as user.address().

  • Capturing a function on non-modules, such as &user.address/0.

  • Attempting to call an anonymous function without an actual function, such as user.().

  • Performing structural comparisons between structs, such as my_date < ~D[2010-04-17].

  • Performing structural comparisons between non-overlapping types, such as integer >= string.

  • Building and pattern matching on binaries without the relevant specifiers, such as <<name>> (this warns because by default it expects an integer, it should have been <<name::binary>> instead).

  • Attempting to rescue an undefined exception or a struct that is not an exception.

  • Accessing a field that is not defined in a rescued exception.

Here’s an example of how the warning for accessing a misspelled field of a struct looks like:

Example of a warning when accessing a mispelled struct field

Another example, this time it’s a warning for structural comparison across two Date structs:

Example of a warning when comparing two structs with ">"

These warnings also work natively in text editors, as they are standard Elixir compiler warnings:

Example of a type warning inline in an editor

These new warnings will help Elixir developers find bugs earlier and give more confidence when refactoring code, especially around maps and structs. While Elixir already emitted some of these warnings in the past, those were discovered using syntax analysis. The new warnings are more reliable, precise, and with better error messages. Keep in mind, however, that the Elixir typechecker only infers types from patterns within the same function at the moment. Analysis from guards and across function boundaries will be added in future releases. For more details, see our new reference document on gradual set-theoretic types.

The type system was made possible thanks to a partnership between CNRS and Remote. The development work is currently sponsored by Fresha (they are hiring!), Starfish*, and Dashbit.

Erlang/OTP support

This release adds support for Erlang/OTP 27 and drops support for Erlang/OTP 24. We recommend Elixir developers to migrate to Erlang/OTP 26 or later, especially on Windows. Support for WERL (a graphical user interface for the Erlang terminal on Windows) will be removed in Elixir v1.18.

You can read more about Erlang/OTP 27 in their release announcement. The bits that are particularly interesting for Elixir developers are the addition of a json module and process labels (proc_lib:set_label/1). The latter will also be available in this Elixir release as Process.set_label/1.

New Duration data type and shifting functions

This Elixir version introduces the Duration data type and APIs to shift dates, times, and date times by a given duration, considering different calendars and time zones.

iex> Date.shift(~D[2016-01-31], month: 2)
~D[2016-03-31]

We chose the name “shift” for this operation (instead of “add”) since working with durations does not obey properties such as associativity. For instance, adding one month and then one month does not give the same result as adding two months:

iex> ~D[2016-01-31] |> Date.shift(month: 1) |> Date.shift(month: 1)
~D[2016-03-29]

Still, durations are essential for building intervals, recurring events, and modelling scheduling complexities found in the world around us. For DateTimes, Elixir will correctly deal with time zone changes (such as Daylight Saving Time). However, provisions are also available in case you want to surface conflicts, such as shifting to a wall clock that does not exist, because the clock has been moved forward by one hour. See DateTime.shift/2 for examples.

Finally, we added a new Kernel.to_timeout/1 function, which helps developers normalize durations and integers to a timeout used by many APIs—like Process, GenServer, and more. For example, to send a message after one hour, you can now write:

Process.send_after(pid, :wake_up, to_timeout(hour: 1))

Learn more

Here are other notable changes in this release:

  • There are new Keyword.intersect/2,3 functions to mirror the equivalent in the Map module.

  • A new Mix profiler was added, mix profile.tprof, which lets you use the new tprof profiler released with Erlang/OTP 27. This profiler leads to the soft-deprecation of mix profile.cprof and mix profile.eprof.

  • We added Kernel.is_non_struct_map/1, a new guard to help with the common pitfall of matching on %{}, which also successfully matches structs (as they are maps underneath).

  • Elixir’s Logger now formats gen_statem reports and includes Erlang/OTP 27 process labels in logger events.

For a complete list of all changes, see the full release notes.

Check the Install section to get Elixir installed and read our Getting Started guide to learn more.

Happy learning!

Permalink

The Review Is the Action Item

2024/05/30

The Review Is the Action Item

I like to consider running an incident review to be its own action item. Other follow-ups emerging from it are a plus, but the point is to learn from incidents, and the review gives room for that to happen.

This is not surprising advice if you’ve read material from the LFI community and related disciplines. However, there are specific perspectives required to make this work, and some assumptions necessary for it, without which things can break down.

How can it work?

In a more traditional view, the system is believed to be stable, then disrupted into an incident. The system gets stabilized, and we must look for weaknesses that can be removed or barriers that could be added in order to prevent such disruption in the future.

Other perspectives for systems include views where they are never truly stable. Things change constantly; uncertainty is normal. Under that lens, systems can’t be forced into stability by control or authority. They can be influenced and adapt on an ongoing basis, and possibly kept in balance through constant effort.

Once you adopt a socio-technical perspective, the hard-to-model nature of humans becomes a desirable trait to cope with chaos. Rather than a messy variable to stamp out, you’ll want to give them more tools and ways to keep all the moving parts of the subsystems going.

There, an incident review becomes an arena where misalignment in objectives can be repaired, where strategies and tactics can be discussed, where mental models can be corrected and enriched, where voices can be heard when they wouldn’t be, and where we are free to reflect on the messy reality that drove us here.

This is valuable work, and establishing an environment where it takes place is a key action item on its own.

People who want to keep things working will jump on this opportunity if they see any value in it. Rather than giving them tickets to work on, we’re giving them a safe context to surface and discuss useful information. They’ll carry that information with them in the future, and it may influence the decisions they make, here and elsewhere.

If the stories that come out of reviews are good enough, they will be retold to others, and the organization will have learned something.

That belief people will do better over time as they learn, to me, tends to be worth more than focusing on making room for a few tickets in the backlog.

How can it break down?

One of the unnamed assumptions with this whole approach is that teams should have the ability to influence their own roadmap and choose some of their own work.

A staunchly top-down organization may leverage incident reviews as a way to let people change the established course with a high priority. That use of incident reviews can’t be denied in these contexts.

We want to give people the information and the perspectives they need to come up with fixes that are effective. Good reviews with action items ought to make sense, particularly in these orgs where most of the work is normally driven by folks outside of the engineering teams.

But if the maintainers do not have the opportunity to schedule work they think needs doing outside of the aftermath of an incident—work that is by definition reactive—then they have no real power to schedule preventive work on their own.

And so that’s a place where learning being its own purpose breaks down: when the learnings can’t be applied.

Maybe it feels like “good” reviews focused on learning apply to a surprisingly narrow set of teams then, because most teams don’t have that much control. The question here really boils down to “who is it that can apply things they learned, and when?”

If the answer is “almost no one, and only when things explode,” that’s maybe a good lesson already. That’s maybe where you’d want to start remediating.

Note that even this perspective is a bit reductionist, which is also another way in which learning reviews may break down. By narrowing knowledge’s utility only to when it gets applied in measurable scheduled work, we stop finding value outside of this context, and eventually stop giving space for it.

It’s easy to forget that we don’t control what people learn. We don’t choose what the takeaways are. Everyone does it for themselves based on their own lived experience. More importantly, we can’t stop people from using the information they learned, whether at work or in their personal life.

Lessons learned can be applied anywhere and any time, and they can become critically useful at unexpected times. Narrowing the scope of your reviews such that they only aim to prevent bad accidents indirectly hinders creating fertile grounds for good surprises as well.

Going for better

While the need for action items is almost always there, a key element of improving incident reviews is to not make corrections the focal point.

Consider the incident review as a preliminary step, the data-gathering stage before writing down the ideas. You’re using recent events as a study of what’s surprising within the system, but also of how it is that things usually work well. Only once that perspective is established does it make sense to start thinking of ways of modifying things.

Try it with only one or two reviews at first. Minor incidents are usually good, because following the methods outlined in docs like the Etsy Debriefing Facilitation Guide and the Howie guide tends to reveal many useful insights in incidents people would have otherwise overlooked as not very interesting.

As you and your teams see value, expand to more and more incidents.

It also helps to set the tone before and during the meetings. I’ve written a set of “ground rules” we use at Honeycomb and that my colleague Lex Neva has transcribed, commented, and published. See if something like that could adequately frame the session..

If abandoning the idea of action items seems irresponsible or impractical to you, keep them. But keep them with some distance; the common tip given by the LFI community is to schedule another meeting after the review to discuss them in isolation. iiii At some point, that follow-up meeting may become disjoint from the reviews. There’s not necessarily a reason why every incident needs a dedicated set of fixes (longer-term changes impacting them could already be in progress, for example), nor is there a reason to wait for an incident to fix things and improve them.

That’s when you decouple understanding from fixing, and the incident review becomes its own sufficient action item.

Permalink

Building Erlang 26.2.5 on Ubuntu 24.04

A new Ubuntu LTS, a new set of minor package naming annoyances. Here is the current process:

sudo apt update
sudo apt upgrade
sudo apt install \
    gcc curl g++ dpkg-dev build-essential automake autoconf \
    libncurses-dev libssl-dev flex xsltproc libwxgtk3.2-dev \
    wget vim git
mkdir -p ~/vcs ~/bin
cd ~/vcs
kerl build 26.2.5 26.2.5
kerl install 26.2.5 ~/.erts/26.2.5
echo '. "$HOME"/.erts/26.2.5/activate' >> .bashrc
. ~/.erts/26.2.5/activate
wget -q https://zxq9.com/projects/zomp/get_zx && bash get_zx

Permalink

Erlang/OTP 27.0 Release

Erlang/OTP 27 is a new major release with new features, improvements as well as a few incompatibilities.

For details about new features, bugfixes and potential incompatibilities see the Erlang 27.0 README or the Erlang/OTP 27.0 downloads page.

Many thanks to all contributors!

Below are some of the highlights of the release:

Documentation

EEP-59 has been implemented. Documentation attributes in source files can now be used to document functions, types, callbacks, and modules.

The entire Erlang/OTP documentation is now using the new documentation system.

Building Erlang/OTP

  • configure now automatically enables support for year-2038-safe timestamps.

    By default configure scripts used when building OTP will now try to enable support for timestamps that will work after mid-January 2038. This has typically only been an issue on 32-bit platforms.

    If configure cannot figure out how to enable such timestamps, it will abort with an error message. If you want to build the system anyway, knowing that the system will not function properly after mid-January 2038, you can pass the --disable-year2038 option to configure, which will enable configure to continue without support for timestamps after mid-January 2038.

New language features

  • Triple-Quoted Strings has been implemented as per EEP 64 to allow a string to encompass a complete paragraph.

  • Adjacent string literals without intervening white space is now a syntax error, to avoid possible confusion with triple-quoted strings.

  • Sigils on string literals (both ordinary and triple-quoted) have been implemented as per EEP 66. For example, ~"Björn" or ~b"Björn" are now equivalent to <<"Björn"/utf8>>.

Compiler and JIT improvements

  • The compiler will now merge consecutive updates of the same record.

  • Safe destructive update of tuples has been implemented in the compiler and runtime system. This allows the VM to update tuples in-place when it is safe to do so, thus improving performance by doing less copying but also by producing less garbage.

  • The maybe expression is now enabled by default, eliminating the need for enabling the maybe_expr feature.

  • Native coverage support has been implemented in the JIT. It will automatically be used by the cover tool to reduce the execution overhead when running cover-compiled code. There are also new APIs to support native coverage without using the cover tool.

  • The compiler will now raise a warning when updating record/map literals to catch a common mistake. For example, the compiler will now emit a warning for #r{a=1}#r{b=2}.

ERTS

  • The erl command now supports the -S flag, which is similar to the -run flag, but with some of the rough edges filed off.

  • By default, escripts will now be compiled instead of interpreted. That means that the compiler application must be installed.

  • The default process limit has been raised to 1048576 processes.

  • The erlang:system_monitor/2 functionality is now able to monitor long message queues in the system.

  • The obsolete and undocumented support for opening a port to an external resource by passing an atom (or a string) as first argument to open_port(), implemented by the vanilla driver, has been removed. This feature has been scheduled for removal in OTP 27 since the release of OTP 26.

  • The pid field has been removed from erlang:fun_info/1,2.

  • Multiple trace sessions are now supported.

STDLIB

  • There is a new module json for encoding and decoding JSON.

    Both encoding and decoding can be customized. Decoding can be done in a SAX-like fashion and handle multiple documents and streams of data.

    The new json module is used by the jer (JSON Encoding Rules) for ASN.1 for encoding and decoding JSON. Thus, there is no longer any need to supply an external JSON library.

  • Several new functions that accept funs have been added to module timer.

  • The functions is_equal/2, map/2, and filtermap/2 have been added to the modules sets, ordsets, and gb_sets.

  • There are new efficient ets traversal functions with guaranteed atomicity. For example, ets:next/2 followed by ets:lookup/2 can now be replaced with ets:next_lookup/1.

  • The new function ets:update_element/4 is similar to ets:update_element/3, but takes a default tuple as the fourth argument, which will be inserted if no previous record with that key exists.

  • binary:replace/3,4 now supports using a fun for supplying the replacement binary.

  • The new function proc_lib:set_label/1 can be used to add a descriptive term to any process that does not have a registered name. The name will be shown by tools such as c:i/0 and observer, and it will be included in crash reports produced by processes using gen_server, gen_statem, gen_event, and gen_fsm.

  • Added functions to retrieve the next higher or lower key/element from gb_trees and gb_sets, as well as returning iterators that start at given keys/elements.

common_test

  • Calls to ct:capture_start/0 and ct:capture_stop/0 are now synchronous to ensure that all output is captured.

  • The default CSS will now include a basic dark mode handling if it is preferred by the browser.

crypto

  • The functions crypto_dyn_iv_init/3 and crypto_dyn_iv_update/3 that were marked as deprecated in Erlang/OTP 25 have been removed.

dialyzer

  • The --gui option for Dialyzer has been removed.

ssl

  • The ssl client can negotiate and handle certificate status request (OCSP stapling support on the client side).

tools

  • There is a new tool tprof, which combines the functionality of eprof and cprof under one interface. It also adds heap profiling.

xmerl

  • As an alternative to xmerl_xml, a new export module xmerl_xml_indent that provides out-of-the box indented output has been added.

For more details about new features and potential incompatibilities see the README.

Permalink

Least Privilege And Elixir Ecto

What’s Least Privilege?

Before diving in to the heart of this blog post I think it’s wise to explain what I mean by “Least Privilege” and why it’s worth while. I think it’s also worth discussing why you may not want to bother with it as well.

The “Principle of Least Privilege” basically means you enable a user to do what they need to do but nothing more. If a user only needs to create reports against a database then it’s usually acceptable to give them permissions to query the database and nothing else. You surely don’t need to give a user who needs to create reports the ability to modify the privileges of other users; that’s unnecessary and might cause big problems.

Some of you may be old enough to remember a time when the Windows operating system was plagued by lots and lots of worms and viruses. This was for the simple reason that before the Vista version of Windows, all users on the machine were effectively superusers (or root depending on one’s frame of reference). This, of course, arose from the fact that Windows was originally intended to be used by a single user on a single machine before connectivity was much of a concern. Why would you block someone from doing whatever they want on a machine if you anticipated that they’d be installing their own software? After all PC did mean personal computer right?

Of course as time progressed, computers were networked and connected to the internet. I remember a less computer-literate friend of mine that simply connected to the internet before anyone had installed a firewall for him and immediately his PC was infected with a virus. I installed a firewall on his machine and cleaned things up but he asked me “What did I do? I just checked my email?” and I had to tell him that the simple act of connecting to the internet without a firewall present was enough to expose his machine to a virus.

Now if you’re 100% sure that your application will never ever be connected to the internet, then you don’t need to worry about least privilege. But the likelihood of no connection to the internet reached zero about 20 years ago and today if it’s even less likely, if that’s possible, that a machine will never connect to the internet. Of course we’ve got firewalls, and we’ve got routers to secure things between us and the internet. But even so there are ways to hack machines which have firewalls. And once someone has gotten in to your network, you don’t want them to be able to get at all the data without some sort of validation.

Bear in mind too that keeping people from seeing sensitive data is not the only concern you should have as a developer. If someone can hack your database (or your machine) they can use it to store illicit data. And if you’re like most developers chances are you’ll store application permissions and id’s in the database itself. The wisdom of storing id’s in a database is questionable but again, this is something we need to be aware of as developers.

I may have said “you might not want to bother with least privilege” but it’s hard for me to imagine a situation where it truly isn’t something you want to make the effort to implement.

Secured In The Application Or Secured At The Database?

Another thing that a developer must consider is exactly where he or she secures the data in the database. You can, of course, secure permissions in the application. In fact this is a very common scenario and it’s usually effective and has some real advantages. It’s more likely that your developers will know the language the application is written in and therefore be better able to understand the implications of the security code. If you need to create new permissions, you can modify the source code and you don’t need to worry about the database per se.

The other option is security at the database level. This is a bit harder to create and maintain but it’s also a lot more secure. When security is enforced at the application level a knowledgeable user can circumvent the application (and its protections) and get at data which he or she should not have access to.

Securing at the database level may require more work and it might require a team to have a DBA on staff. Of course having a database specialist on a team isn’t ever a bad idea–at least in my experience. And even if you make the choice to secure the application via application code, it’s still very wise to be quite stingy with what you let users see. You’re much better to give a user too few permissions than too many.

This also conforms more closely to the idea of Zero Trust Networks. That is, no one on the network is trustworthy–including your application.

I want to emphasize that this is not an either/or choice. It’s entirely possible to have some of your security in the application and some in the database. As long as you code your application to deal with the results of attempts to do things which the user is not permitted to do you’re fine.

Having said all this Elixir (and as far as I know Ruby On Rails) favors the security in the application model. Again, there’s no reason to prefer one approach versus the other–it’s just the way that Elixir was designed to interact with Ecto. The ability to perform database migrations is a large, large advantage over the alternative and making this possible at the database level would be quite tricky.

The main reason I want to secure things at the database level is for security for publicly available database. If a database is unlikely to be publicly accessible, then there’s considerably less one needs to worry about in terms of security. I’m working on an application which will host a database publicly so my tendency to being a little paranoid has made me investigate how I can move my security to the database level.

Admittedly this can be a sort of belt and suspenders approach; that is, it’s a little redundant but it’s also more secure. It’s far closer to the underlying notion informing a zero-trust network approach.

Some Additional Preliminaries

1.) Given the prevalence of PostgreSQL in Elixir application use the code in this post will assume you’re working with a PgSQL back-end. The ideas should work equally well with other databases but figuring out the exact Data Definition Language and/or SQL needed is left as an exercise for the reader.

2.) For the purposes of this post, I’m creating a read-only (RO) user and a read-write (RW) user. There are certainly other combinations which can be created. The main point is to provide a user who has privileges tailored to the work it will need to do so that it cannot be exploited by bad actors to mess with your database.

3.) I’ve tested the RO and the RW user with various scenarios and no obvious issues have presented themselves. Be warned though that my testing has not been very extensive since I’ve been creating this implementation for a personal project so bear that in mind.

All that out of the way, let’s finally get to some code shall we?

Creating the Users

Here’s the code I’ve used to create the RO and RW users.

# Create custom users for reading data and writing data
defmodule LeastPrivilege do
  @moduledoc """
  Create database users with the least privileges necessary to perform their tasks.
  """

  @spec create_nonadmin_user(String.t(), String.t()) :: query_result.t()
  defp create_nonadmin_user(user_name, password) do
    Ecto.Adapters.SQL.query!(
      Pta.Repo,
      "CREATE USER #{user_name} WITH NOSUPERUSER NOCREATEDB NOCREATEROLE NOINHERIT LOGIN PASSWORD #{password};"
    )
  end

  @spec grant_table_privileges(String.t(), [String.t()], [String.t()]) :: query_result.t()
  defp grant_table_privileges(user_name, privileges, tables) do
    for table <- tables do
      for privilege <- privileges do
        Ecto.Adapters.SQL.query!(
          Pta.Repo,
          "GRANT #{privilege} ON TABLE #{table} TO #{user_name};"
        )
      end
    end
  end

  @spec create_query_only_user() :: query_result.t()
  def create_query_only_user do
    pta_query_password = "'" <> System.fetch_env!("PTA_QUERY_PASSWORD") <> "'"
    user_name = "pta_query"

    create_nonadmin_user(user_name, pta_query_password)
    grant_table_privileges(user_name, ["SELECT"], ["venues", "performances"])
    grant_table_privileges(user_name, ["ALL PRIVILEGES"], ["schema_migrations"])
    Ecto.Adapters.SQL.query!(Pta.Repo, "GRANT pg_read_all_data TO #{user_name};")
    Ecto.Adapters.SQL.query!(Pta.Repo, "GRANT CREATE ON SCHEMA public TO #{user_name};")
  end

  @spec create_readwrite_user() :: query_result.t()
  def create_readwrite_user do
    pta_update_password = "'" <> System.fetch_env!("PTA_UPDATE_PASSWORD") <> "'"
    user_name = "pta_update"

    create_nonadmin_user(user_name, pta_update_password)

    grant_table_privileges(user_name, ["SELECT", "INSERT", "UPDATE", "DELETE"], [
      "venues",
      "performances"
    ])

    grant_table_privileges(user_name, ["ALL PRIVILEGES"], ["schema_migrations"])
    Ecto.Adapters.SQL.query!(Pta.Repo, "GRANT pg_write_all_data TO #{user_name};")
    Ecto.Adapters.SQL.query!(Pta.Repo, "GRANT CREATE ON SCHEMA public TO #{user_name};")
  end
end

LeastPrivilege.create_query_only_user()
LeastPrivilege.create_readwrite_user()

A few notes on this code:

1.) I’ve created this as a separate module but I use it included in my seeds.exs file. This is for the simple reason that if I need to re-initialize the database (via a mix ecto.reset or a similar mechanism) I want to insure that my special least-privileged users get created as well.

2.) You may notice that all of the functions return a query_result. This is the normal behavior of the Ecto.Adapters.SQL.query function; in this case we’re not actually querying any tables but the return type is nonetheless query_result.

3.) In this particular case I’m using two tables. I’m unaware of any reason to believe that these techniques wouldn’t scale up to far more tables and/or privileges.

4.) There are a few grants which might puzzle the reader:

grant_table_privileges(user_name, ["ALL PRIVILEGES"], ["schema_migrations"])
Ecto.Adapters.SQL.query!(Pta.Repo, "GRANT CREATE ON SCHEMA public TO #{user_name};")

These privileges are a concession to the necessity of working with Ecto. I haven’t researched why they needed but I can say for certain that if I attempt to get away with not specifying both privileges I see errors from Ecto.

5.) The operations in this module must be run under a SUPERUSER connection to the database. That is you cannot create a RW user and then log in under that user and create a RO user. Both must be created while the enduser is connected via SUPERUSER. After they’re created you can use the least privileged users (see below).

Using The Least Privileged Users

Finally it’s not very difficult to actually use the least privileged users in your code. For example, if you wanted to use the RW user as your default user within the database you could modify your dev.exs config file in this fashion.

# Configure your database
config :pta, Pta.Repo,
  username: "pta_update",
  password: *** password ***,
  hostname: "localhost",
  database: "pta_dev",
  stacktrace: true,
  show_sensitive_data_on_connection_error: true,
  pool_size: 10

I haven’t done the work yet to allow me to modify the user dynamically in the code. Again, since I haven’t needed it yet, I haven’t bothered with it.

I hope this blog post helps others who might want to modify their Elixir application to push the database security to the database layer.

Permalink

Erlang/OTP 27.0 Release Candidate 3

OTP 27.0-rc3

Erlang/OTP 27.0-rc3 is the third and final release candidate before the OTP 27.0 release.

The intention with this release is to get feedback from our users. All feedback is welcome, even if it is only to say that it works for you. We encourage users to try it out and give us feedback either by creating an issue at https://github.com/erlang/otp/issues or by posting to Erlang Forums.

All artifacts for the release can be downloaded from the Erlang/OTP Github release and you can view the new documentation at https://erlang.org/documentation/doc-15.0-rc3/doc. You can also install the latest release using kerl like this:

kerl build 27.0-rc3 27.0-rc3.

Erlang/OTP 27 is a new major release with new features, improvements as well as a few incompatibilities. Some of the new features are highlighted below.

Many thanks to all contributors!

Notable changes in RC3

  • The support for multiple trace sessions is now documented and ready for use.

Highlights for RC2

  • There is a new module json for encoding and decoding JSON.

    Both encoding and decoding can be customized. Decoding can be done in a SAX-like fashion and handle multiple documents and streams of data.

    The new json module is used by the jer (JSON Encoding Rules) for ASN.1 for encoding and decoding JSON. Thus, there is no longer any need to supply an external JSON library.

Other notable changes in RC2

  • The existing experimental support for archive files will be changed in a future release. The support for having an archive in an escript will remain, but the support for using archives in a release will either become more limited or completely removed.

    As of Erlang/OTP 27, the function code:lib_dir/2, the -code_path_choice flag, and using erl_prim_loader for reading members of an archive are deprecated.

    To remain compatible with future version of Erlang/OTP escript scripts that need to retrieve data files from its archive should use escript:extract/2 instead of erl_prim_loader and code:lib_dir/2.

  • The order in which the compiler looks up options has changed.

    When there is a conflict in the compiler options given in the -compile() attribute and options given to the compiler, the options given in the -compile() attribute overrides the option given to the compiler, which in turn overrides options given in the ERL_COMPILER_OPTIONS environment variable.

    Example:

    If some_module.erl has the following attribute:

    -compile([nowarn_missing_spec]).
    

    and the compiler is invoked like so:

    % erlc +warn_missing_spec some_module.erl
    

    no warnings will be issued for functions that do not have any specs.

  • configure now automatically enables support for year-2038-safe timestamps.

    By default configure scripts used when building OTP will now try to enable support for timestamps that will work after mid-January 2038. This has typically only been an issue on 32-bit platforms.

    If configure cannot figure out how to enable such timestamps, it will abort with an error message. If you want to build the system anyway, knowing that the system will not function properly after mid-January 2038, you can pass the --disable-year2038 option to configure, which will enable configure to continue without support for timestamps after mid-January 2038.

Highlights for RC1

Documentation

EEP-59 has been implemented. Documentation attributes in source files can now be used to document functions, types, callbacks, and modules.

The entire Erlang/OTP documentation is now using the new documentation system.

New language features

  • Triple-Quoted Strings has been implemented as per EEP 64 to allow a string to encompass a complete paragraph.

  • Adjacent string literals without intervening white space is now a syntax error, to avoid possible confusion with triple-quoted strings.

  • Sigils on string literals (both ordinary and triple-quoted) have been implemented as per EEP 66. For example, ~"Björn" or ~b"Björn" are now equivalent to <<"Björn"/utf8>>.

Compiler and JIT improvements

  • The compiler will now merge consecutive updates of the same record.

  • Safe destructive update of tuples has been implemented in the compiler and runtime system. This allows the VM to update tuples in-place when it is safe to do so, thus improving performance by doing less copying but also by producing less garbage.

  • The maybe expression is now enabled by default, eliminating the need for enabling the maybe_expr feature.

  • Native coverage support has been implemented in the JIT. It will automatically be used by the cover tool to reduce the execution overhead when running cover-compiled code. There are also new APIs to support native coverage without using the cover tool.

  • The compiler will now raise a warning when updating record/map literals to catch a common mistake. For example, the compiler will now emit a warning for #r{a=1}#r{b=2}.

ERTS

  • The erl command now supports the -S flag, which is similar to the -run flag, but with some of the rough edges filed off.

  • By default, escripts will now be compiled instead of interpreted. That means that the compiler application must be installed.

  • The default process limit has been raised to 1048576 processes.

  • The erlang:system_monitor/2 functionality is now able to monitor long message queues in the system.

  • The obsolete and undocumented support for opening a port to an external resource by passing an atom (or a string) as first argument to open_port(), implemented by the vanilla driver, has been removed. This feature has been scheduled for removal in OTP 27 since the release of OTP 26.

  • The pid field has been removed from erlang:fun_info/1,2.

  • Multiple trace sessions are now supported.

STDLIB

  • Several new functions that accept funs have been added to module timer.

  • The functions is_equal/2, map/2, and filtermap/2 have been added to the modules sets, ordsets, and gb_sets.

  • There are new efficient ets traversal functions with guaranteed atomicity. For example, ets:next/2 followed by ets:lookup/2 can now be replaced with ets:next_lookup/1.

  • The new function ets:update_element/4 is similar to ets:update_element/3, but takes a default tuple as the fourth argument, which will be inserted if no previous record with that key exists.

  • binary:replace/3,4 now supports using a fun for supplying the replacement binary.

  • The new function proc_lib:set_label/1 can be used to add a descriptive term to any process that does not have a registered name. The name will be shown by tools such as c:i/0 and observer, and it will be included in crash reports produced by processes using gen_server, gen_statem, gen_event, and gen_fsm.

  • Added functions to retrieve the next higher or lower key/element from gb_trees and gb_sets, as well as returning iterators that start at given keys/elements.

common_test

  • Calls to ct:capture_start/0 and ct:capture_stop/0 are now synchronous to ensure that all output is captured.

  • The default CSS will now include a basic dark mode handling if it is preferred by the browser.

crypto

  • The functions crypto_dyn_iv_init/3 and crypto_dyn_iv_update/3 that were marked as deprecated in Erlang/OTP 25 have been removed.

dialyzer

  • The --gui option for Dialyzer has been removed.

ssl

  • The ssl client can negotiate and handle certificate status request (OCSP stapling support on the client side).

tools

  • There is a new tool tprof, which combines the functionality of eprof and cprof under one interface. It also adds heap profiling.

xmerl

  • As an alternative to xmerl_xml, a new export module xmerl_xml_indent that provides out-of-the box indented output has been added.

For more details about new features and potential incompatibilities see the README.

Permalink

Erlang/OTP 27.0 Release Candidate 2

OTP 27.0-rc2

Erlang/OTP 27.0-rc2 is the second release candidate of three before the OTP 27.0 release.

The intention with this release is to get feedback from our users. All feedback is welcome, even if it is only to say that it works for you. We encourage users to try it out and give us feedback either by creating an issue at https://github.com/erlang/otp/issues or by posting to Erlang Forums.

All artifacts for the release can be downloaded from the Erlang/OTP Github release and you can view the new documentation at https://erlang.org/documentation/doc-15.0-rc2/doc. You can also install the latest release using kerl like this:

kerl build 27.0-rc2 27.0-rc2.

Erlang/OTP 27 is a new major release with new features, improvements as well as a few incompatibilities. Some of the new features are highlighted below.

Many thanks to all contributors!

Highlights for RC2

  • There is a new module json for encoding and decoding JSON.

    Both encoding and decoding can be customized. Decoding can be done in a SAX-like fashion and handle multiple documents and streams of data.

    The new json module is used by the jer (JSON Encoding Rules) for ASN.1 for encoding and decoding JSON. Thus, there is no longer any need to supply an external JSON library.

Other notable changes in RC2

  • The existing experimental support for archive files will be changed in a future release. The support for having an archive in an escript will remain, but the support for using archives in a release will either become more limited or completely removed.

    As of Erlang/OTP 27, the function code:lib_dir/2, the -code_path_choice flag, and using erl_prim_loader for reading members of an archive are deprecated.

    To remain compatible with future version of Erlang/OTP escript scripts that need to retrieve data files from its archive should use escript:extract/2 instead of erl_prim_loader and code:lib_dir/2.

  • The order in which the compiler looks up options has changed.

    When there is a conflict in the compiler options given in the -compile() attribute and options given to the compiler, the options given in the -compile() attribute overrides the option given to the compiler, which in turn overrides options given in the ERL_COMPILER_OPTIONS environment variable.

    Example:

    If some_module.erl has the following attribute:

    -compile([nowarn_missing_spec]).
    

    and the compiler is invoked like so:

    % erlc +warn_missing_spec some_module.erl
    

    no warnings will be issued for functions that do not have any specs.

  • configure now automatically enables support for year-2038-safe timestamps.

    By default configure scripts used when building OTP will now try to enable support for timestamps that will work after mid-January 2038. This has typically only been an issue on 32-bit platforms.

    If configure cannot figure out how to enable such timestamps, it will abort with an error message. If you want to build the system anyway, knowing that the system will not function properly after mid-January 2038, you can pass the --disable-year2038 option to configure, which will enable configure to continue without support for timestamps after mid-January 2038.

Highlights for RC1

Documentation

EEP-59 has been implemented. Documentation attributes in source files can now be used to document functions, types, callbacks, and modules.

The entire Erlang/OTP documentation is now using the new documentation system.

New language features

  • Triple-Quoted Strings has been implemented as per EEP 64 to allow a string to encompass a complete paragraph.

  • Adjacent string literals without intervening white space is now a syntax error, to avoid possible confusion with triple-quoted strings.

  • Sigils on string literals (both ordinary and triple-quoted) have been implemented as per EEP 66. For example, ~"Björn" or ~b"Björn" are now equivalent to <<"Björn"/utf8>>.

Compiler and JIT improvements

  • The compiler will now merge consecutive updates of the same record.

  • Safe destructive update of tuples has been implemented in the compiler and runtime system. This allows the VM to update tuples in-place when it is safe to do so, thus improving performance by doing less copying but also by producing less garbage.

  • The maybe expression is now enabled by default, eliminating the need for enabling the maybe_expr feature.

  • Native coverage support has been implemented in the JIT. It will automatically be used by the cover tool to reduce the execution overhead when running cover-compiled code. There are also new APIs to support native coverage without using the cover tool.

  • The compiler will now raise a warning when updating record/map literals to catch a common mistake. For example, the compiler will now emit a warning for #r{a=1}#r{b=2}.

ERTS

  • The erl command now supports the -S flag, which is similar to the -run flag, but with some of the rough edges filed off.

  • By default, escripts will now be compiled instead of interpreted. That means that the compiler application must be installed.

  • The default process limit has been raised to 1048576 processes.

  • The erlang:system_monitor/2 functionality is now able to monitor long message queues in the system.

  • The obsolete and undocumented support for opening a port to an external resource by passing an atom (or a string) as first argument to open_port(), implemented by the vanilla driver, has been removed. This feature has been scheduled for removal in OTP 27 since the release of OTP 26.

  • The pid field has been removed from erlang:fun_info/1,2.

  • Multiple trace sessions are now supported.

STDLIB

  • Several new functions that accept funs have been added to module timer.

  • The functions is_equal/2, map/2, and filtermap/2 have been added to the modules sets, ordsets, and gb_sets.

  • There are new efficient ets traversal functions with guaranteed atomicity. For example, ets:next/2 followed by ets:lookup/2 can now be replaced with ets:next_lookup/1.

  • The new function ets:update_element/4 is similar to ets:update_element/3, but takes a default tuple as the fourth argument, which will be inserted if no previous record with that key exists.

  • binary:replace/3,4 now supports using a fun for supplying the replacement binary.

  • The new function proc_lib:set_label/1 can be used to add a descriptive term to any process that does not have a registered name. The name will be shown by tools such as c:i/0 and observer, and it will be included in crash reports produced by processes using gen_server, gen_statem, gen_event, and gen_fsm.

  • Added functions to retrieve the next higher or lower key/element from gb_trees and gb_sets, as well as returning iterators that start at given keys/elements.

common_test

  • Calls to ct:capture_start/0 and ct:capture_stop/0 are now synchronous to ensure that all output is captured.

  • The default CSS will now include a basic dark mode handling if it is preferred by the browser.

crypto

  • The functions crypto_dyn_iv_init/3 and crypto_dyn_iv_update/3 that were marked as deprecated in Erlang/OTP 25 have been removed.

dialyzer

  • The --gui option for Dialyzer has been removed.

ssl

  • The ssl client can negotiate and handle certificate status request (OCSP stapling support on the client side).

tools

  • There is a new tool tprof, which combines the functionality of eprof and cprof under one interface. It also adds heap profiling.

xmerl

  • As an alternative to xmerl_xml, a new export module xmerl_xml_indent that provides out-of-the box indented output has been added.

For more details about new features and potential incompatibilities see the README.

Permalink

Copyright © 2016, Planet Erlang. No rights reserved.
Planet Erlang is maintained by Proctor.